Initialize the project.
[platform/framework/web/livebox-viewer.git] / live.viewer / src / lb.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.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.tizenopensource.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 <Elementary.h>
18 #include <Ecore_X.h>
19
20 #include <dlog.h>
21
22 #include <livebox.h>
23 #include <livebox-service.h>
24
25 #include "main.h"
26 #include "util.h"
27 #include "debug.h"
28 #include "lb.h"
29 #include "scroller.h"
30
31 #define FLICK_COND      100
32
33 static Evas_Object *create_canvas(Evas_Object *parent)
34 {
35         Evas_Object *canvas;
36
37         canvas = evas_object_image_filled_add(evas_object_evas_get(parent));
38         if (!canvas)
39                 return NULL;
40
41         evas_object_image_colorspace_set(canvas, EVAS_COLORSPACE_ARGB8888);
42         evas_object_image_alpha_set(canvas, EINA_TRUE);
43         evas_object_move(canvas, 0, 0);
44         return canvas;
45 }
46
47 static int update_pd_canvas(struct livebox *handle, Evas_Object *image)
48 {
49         int w;
50         int h;
51
52         switch (livebox_pd_type(handle)) {
53         case PD_TYPE_BUFFER:
54         case PD_TYPE_PIXMAP:
55                 evas_object_image_colorspace_set(image, EVAS_COLORSPACE_ARGB8888);
56                 evas_object_image_alpha_set(image, EINA_TRUE);
57
58                 livebox_get_pdsize(handle, &w, &h);
59                 if (w > 0 && h > 0) {
60                         void *data;
61                         data = livebox_acquire_pdfb(handle);
62                         if (data) {
63                                 evas_object_image_size_set(image, w, h);
64                                 evas_object_image_data_copy_set(image, data);
65                                 livebox_release_pdfb(data);
66                         }
67                         evas_object_resize(image, w, h);
68                         //evas_object_size_hint_min_set(image, w, h);
69                         evas_object_size_hint_max_set(image, w, h);
70                 }
71                 break;
72         case PD_TYPE_TEXT:
73         default:
74                 break;
75         }
76
77         return 0;
78 }
79
80 static int update_canvas(struct livebox *handle, Evas_Object *image)
81 {
82         const char *filename;
83         int w;
84         int h;
85         int type;
86
87         switch (livebox_lb_type(handle)) {
88         case LB_TYPE_BUFFER:
89         case LB_TYPE_PIXMAP:
90                 evas_object_image_colorspace_set(image, EVAS_COLORSPACE_ARGB8888);
91                 evas_object_image_alpha_set(image, EINA_TRUE);
92
93                 w = h = 0;
94                 type = livebox_size(handle);
95                 livebox_service_get_size(type, &w, &h);
96                 if (w > 0 && h > 0) {
97                         void *data;
98                         data = livebox_acquire_fb(handle);
99                         if (data) {
100                                 evas_object_image_size_set(image, w, h);
101                                 evas_object_image_data_copy_set(image, data);
102                                 livebox_release_fb(data);
103                         }
104                         evas_object_resize(image, w, h);
105                         evas_object_size_hint_min_set(image, w, h);
106                         evas_object_size_hint_max_set(image, w, h);
107                 }
108                 break;
109         case LB_TYPE_IMAGE:
110                 filename = livebox_filename(handle);
111                 if (filename) {
112                         const char *old;
113                         evas_object_image_file_get(image, &old, NULL);
114                         if (old && !strcmp(filename, old)) {
115                                 evas_object_image_reload(image);
116                         } else {
117                                 evas_object_image_file_set(image, filename, NULL);
118                         }
119
120                         w = h = 0;
121                         type = livebox_size(handle);
122                         livebox_service_get_size(type, &w, &h);
123                         if (w > 0 && h > 0) {
124                                 evas_object_resize(image, w, h);
125                                 evas_object_size_hint_min_set(image, w, h);
126                                 evas_object_size_hint_max_set(image, w, h);
127                         }
128                 }
129                 break;
130         case LB_TYPE_TEXT:
131         default:
132                 break;
133         }
134
135         return 0;
136 }
137
138 static inline void prepend_log(struct livebox *handle, const char *buffer)
139 {
140         Evas_Object *layout;
141         Evas_Object *logger;
142
143         layout = livebox_get_data(handle);
144         if (!layout) {
145                 ErrPrint("Failed to get layout\n");
146                 return;
147         }
148
149         logger = elm_object_part_content_get(layout, "logger");
150         if (logger)
151                 elm_list_item_prepend(logger, buffer, NULL, NULL, NULL, NULL);
152 }
153
154 static int lb_event_cb(struct livebox *handle, enum livebox_event_type event, void *data)
155 {
156         Evas_Object *layout;
157         Evas_Object *sc;
158         Evas_Object *pd;
159         Evas_Object *image;
160
161         layout = (Evas_Object *)livebox_get_data(handle);
162         if (!layout)
163                 return -EFAULT;
164
165         switch (event) {
166         case LB_EVENT_LB_UPDATED:
167                 DbgPrint("Contents: [%s]\n", livebox_content(handle));
168                 image = elm_object_part_content_get(layout, "livebox");
169                 if (image)
170                         update_canvas(handle, image);
171                 break;
172         case LB_EVENT_PD_UPDATED:
173                 image = elm_object_part_content_get(layout, "pd");
174                 if (image)
175                         update_pd_canvas(handle, image);
176                 break;
177         case LB_EVENT_DELETED:
178                 sc = evas_object_data_del(layout, "sc");
179                 if (sc)
180                         scroller_peek_by_obj(sc, layout);
181
182                 evas_object_del(layout);
183                 break;
184         case LB_EVENT_PD_DESTROYED:
185                 pd = elm_object_part_content_unset(layout, "pd");
186                 if (pd)
187                         evas_object_del(pd);
188
189                 sc = evas_object_data_del(layout, "sc");
190                 if (sc)
191                         scroller_unlock(sc);
192                 break;
193         default:
194                 break;
195         }
196
197         return 0;
198 }
199
200 static int lb_fault_cb(enum livebox_fault_type event,
201                                         const char *pkgname, const char *filename,
202                                         const char *funcname, void *data)
203 {
204         DbgPrint("pkgname: %s\nfilename: %s\n:funcname: %s\n", pkgname, filename, funcname);
205         return 0;
206 }
207
208 static void del_cb(struct livebox *handle, int ret, void *data)
209 {
210         Evas_Object *layout = data;
211         Evas_Object *sc;
212
213         sc = evas_object_data_del(layout, "sc");
214         if (sc) {
215                 DbgPrint("Scroller: %p\n", sc);
216                 scroller_peek_by_obj(sc, layout);
217         }
218
219         DbgPrint("Delete a layout object\n");
220         evas_object_del(layout);
221 }
222
223 static void delete_btn_cb(void *handle, Evas_Object *obj, void *event_info)
224 {
225         int ret;
226         Evas_Object *layout;
227         layout = livebox_get_data(handle);
228         DbgPrint("Livebox Get Data %p - %p\n", handle, layout);
229         ret = livebox_del(handle, del_cb, layout);
230         if (ret < 0) {
231                 char buffer[256];
232                 snprintf(buffer, sizeof(buffer), "Delete returns: %d\n", ret);
233                 prepend_log(handle, buffer);
234         }
235 }
236
237 static void exit_cb(void *data, Evas_Object *obj, void *event_info)
238 {
239         evas_object_del(obj);
240 }
241
242 static void error_popup(Evas_Object *parent, struct livebox *handle, int ret)
243 {
244         Evas_Object *popup;
245         Evas_Object *button;
246         char buffer[256];
247
248         popup = elm_popup_add(parent);
249         if (!popup)
250                 return;
251
252         button = elm_button_add(parent);
253         if (!button) {
254                 evas_object_del(popup);
255                 return;
256         }
257
258         elm_popup_orient_set(popup, ELM_POPUP_ORIENT_CENTER);
259         elm_object_part_text_set(popup, "title,text", "Unable to load a livebox");
260
261         elm_object_text_set(button, "Okay");
262         elm_object_part_content_set(popup, "button2", button);
263         evas_object_smart_callback_add(button, "clicked", exit_cb, popup);
264
265         snprintf(buffer, sizeof(buffer) - 1,
266                         "%s(%s): %d", livebox_pkgname(handle), livebox_content(handle), ret);
267         elm_object_part_text_set(popup, "default", buffer);
268         evas_object_show(popup);
269
270         return;
271 }
272
273 static void resize_cb(struct livebox *handle, int ret, void *data)
274 {
275         Evas_Object *layout;
276         Evas_Object *log_list;
277         char buffer[256];
278
279         layout = livebox_get_data(handle);
280         if (!layout)
281                 return;
282
283         log_list = elm_object_part_content_get(layout, "logger");
284         if (!log_list)
285                 return;
286
287         snprintf(buffer, sizeof(buffer) - 1, "Resize: %d", ret);
288         elm_list_item_prepend(log_list, buffer, NULL, NULL, NULL, NULL);
289 }
290
291 static void resize_click_cb(void *handle, Evas_Object *obj, void *event_info)
292 {
293         Elm_Object_Item *item;
294         const char *label;
295         int w;
296         int h;
297         int size_type;
298
299         item = elm_list_selected_item_get(obj);
300         if (!item)
301                 return;
302
303         label = elm_object_item_part_text_get(item, NULL);
304         if (!label)
305                 return;
306
307         sscanf(label, "%dx%d", &w, &h);
308         size_type = livebox_service_size_type(w, h);
309
310         livebox_resize(handle, size_type, resize_cb, NULL);
311 }
312
313 static void create_resize_controller(struct livebox *handle, Evas_Object *layout)
314 {
315         Evas_Object *size_list;
316         char buffer[256];
317         int sizes[7];
318         int cnt;
319         int i;
320         int w;
321         int h;
322
323         size_list = elm_list_add(layout);
324         cnt = 7;
325         livebox_get_supported_sizes(handle, &cnt, sizes);
326         for (i = 0; i < cnt; i++) {
327                 livebox_service_get_size(sizes[i], &w, &h);
328                 snprintf(buffer, sizeof(buffer) - 1, "%dx%d", w, h);
329
330                 elm_list_item_append(size_list, buffer, NULL, NULL, resize_click_cb, handle);
331         }
332         evas_object_show(size_list);
333         elm_list_go(size_list);
334         evas_object_size_hint_weight_set(size_list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
335         evas_object_size_hint_align_set(size_list, EVAS_HINT_FILL, EVAS_HINT_FILL);
336         elm_object_part_content_set(layout, "controller", size_list);
337 }
338
339 static void create_logger(struct livebox *handle, Evas_Object *layout)
340 {
341         Evas_Object *log_list;
342
343         log_list = elm_list_add(layout);
344         if (!log_list)
345                 return;
346
347         elm_list_item_prepend(log_list, "Created", NULL, NULL, NULL, NULL);
348         evas_object_show(log_list);
349         elm_list_go(log_list);
350
351         evas_object_size_hint_weight_set(log_list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
352         evas_object_size_hint_align_set(log_list, EVAS_HINT_FILL, EVAS_HINT_FILL);
353         elm_object_part_content_set(layout, "logger", log_list);
354 }
355
356 struct event_data {
357         Evas_Coord x;
358         Evas_Coord y;
359
360         enum flick {
361                 FLICK_UNKNOWN = 0x00,
362                 FLICK_DOWN = 0x01,
363                 FLICK_UP = 0x02,
364         } flick;
365 };
366
367 static void pd_closed_cb(struct livebox *handle, int ret, void *data)
368 {
369         evas_object_del(data);
370 }
371
372 static void pd_hide_done_cb(void *data, Evas_Object *obj, const char *emission, const char *source) 
373 {
374         Evas_Object *pd;
375         Evas_Object *sc;
376
377         sc = evas_object_data_get(obj, "sc");
378         scroller_unlock(sc);
379
380         elm_object_signal_callback_del(obj, emission, source, pd_hide_done_cb);
381         pd = elm_object_part_content_unset(obj, "pd");
382         livebox_destroy_pd(data, pd_closed_cb, pd);
383 }
384
385 static void pd_mouse_up_cb(void *handle, Evas *e, Evas_Object *obj, void *event_info)
386 {
387         Evas_Event_Mouse_Up *up = event_info;
388         Evas_Coord x, y, w, h;
389         double rx, ry;
390
391         evas_object_geometry_get(obj, &x, &y, &w, &h);
392
393         rx = (double)(up->canvas.x - x) / (double)w;
394         ry = (double)(up->canvas.y - y) / (double)h;
395         livebox_content_event(handle, PD_MOUSE_UP, rx, ry);
396 }
397
398 static void pd_mouse_down_cb(void *handle, Evas *e, Evas_Object *obj, void *event_info)
399 {
400         Evas_Event_Mouse_Down *down = event_info;
401         Evas_Coord x, y, w, h;
402         double rx, ry;
403
404         evas_object_geometry_get(obj, &x, &y, &w, &h);
405         rx = (double)(down->canvas.x - x) / (double)w;
406         ry = (double)(down->canvas.y - y) / (double)h;
407         livebox_content_event(handle, PD_MOUSE_DOWN, rx, ry);
408 }
409
410 static void pd_mouse_move_cb(void *handle, Evas *e, Evas_Object *obj, void *event_info)
411 {
412         Evas_Event_Mouse_Move *move = event_info;
413         Evas_Coord x, y, w, h;
414         double rx, ry;
415
416         evas_object_geometry_get(obj, &x, &y, &w, &h);
417         rx = (double)(move->cur.canvas.x - x) / (double)w;
418         ry = (double)(move->cur.canvas.y - y) / (double)h;
419         livebox_content_event(handle, PD_MOUSE_MOVE, rx, ry);
420 }
421
422 static void pd_created_cb(struct livebox *handle, int ret, void *data)
423 {
424         Evas_Object *layout;
425         Evas_Object *pd_image;
426         Evas_Object *sc;
427
428         layout = (Evas_Object *)livebox_get_data(handle);
429         if (!layout)
430                 return;
431
432         sc = evas_object_data_get(layout, "sc");
433
434         pd_image = create_canvas(layout);
435         if (!pd_image)
436                 return;
437
438         evas_object_event_callback_add(pd_image, EVAS_CALLBACK_MOUSE_UP, pd_mouse_up_cb, handle);
439         evas_object_event_callback_add(pd_image, EVAS_CALLBACK_MOUSE_DOWN, pd_mouse_down_cb, handle);
440         evas_object_event_callback_add(pd_image, EVAS_CALLBACK_MOUSE_MOVE, pd_mouse_move_cb, handle);
441
442         update_pd_canvas(handle, pd_image);
443
444         elm_object_signal_callback_add(layout, "hide,done", "pd", pd_hide_done_cb, handle);
445         elm_object_part_content_set(layout, "pd", pd_image);
446         elm_object_signal_emit(layout, "open", "pd");
447         scroller_lock(sc);
448 }
449
450 static void lb_mouse_up_cb(void *handle, Evas *e, Evas_Object *obj, void *event_info)
451 {
452         Evas_Event_Mouse_Up *up = event_info;
453         struct event_data *evt;
454
455         evt = evas_object_data_del(obj, "evt");
456         if (!evt)
457                 return;
458
459         if (livebox_lb_type(handle) == LB_TYPE_PIXMAP || livebox_lb_type(handle) == LB_TYPE_BUFFER) {
460                 Evas_Coord x, y, w, h;
461                 double rx, ry;
462
463                 evas_object_geometry_get(obj, &x, &y, &w, &h);
464                 rx = (double)(up->canvas.x - x) / (double)w;
465                 ry = (double)(up->canvas.y - y) / (double)h;
466                 livebox_content_event(handle, LB_MOUSE_UP, rx, ry);
467         } else {
468                 Evas_Coord x, y, w, h;
469                 evas_object_geometry_get(obj, &x, &y, &w, &h);
470
471                 if (x < up->canvas.x && up->canvas.x < x + w) {
472                         if (y < up->canvas.y && up->canvas.y < y + h) {
473                                 livebox_click(handle, (double)x / (double)w, (double)y / (double)h);
474                         }
475                 }
476         }
477
478         if (evt->flick == FLICK_DOWN && (up->canvas.y - evt->y) > (FLICK_COND>>1)) {
479                 int ret;
480                 /* Open PD */
481                 ret = livebox_create_pd_with_position(handle, 0.5, 0.0, pd_created_cb, NULL);
482         }
483
484         free(evt);
485 }
486
487 static void lb_mouse_down_cb(void *handle, Evas *e, Evas_Object *obj, void *event_info)
488 {
489         struct event_data *evt;
490         Evas_Event_Mouse_Down *down = event_info;
491         Evas_Object *layout;
492         Evas_Object *sc;
493
494         layout = livebox_get_data(handle);
495         if (!layout)
496                 return;
497
498         sc = evas_object_data_get(layout, "sc");
499         if (!sc)
500                 return;
501
502         if (scroller_is_scrolling(sc))
503                 return;
504
505         if (livebox_lb_type(handle) == LB_TYPE_PIXMAP || livebox_lb_type(handle) == LB_TYPE_BUFFER) {
506                 Evas_Coord x, y, w, h;
507                 double rx, ry;
508
509                 evas_object_geometry_get(obj, &x, &y, &w, &h);
510                 rx = (double)(down->canvas.x - x) / (double)w;
511                 ry = (double)(down->canvas.y - y) / (double)h;
512                 livebox_content_event(handle, LB_MOUSE_DOWN, rx, ry);
513         }
514
515         evt = evas_object_data_get(obj, "evt");
516         if (evt) {
517                 ErrPrint("Huh?");
518         } else {
519                 evt = malloc(sizeof(*evt));
520                 if (!evt) {
521                         ErrPrint("Heap: %s\n", strerror(errno));
522                         return;
523                 }
524         }
525
526         evas_object_data_set(obj, "evt", evt);
527
528         evt->x = down->canvas.x;
529         evt->y = down->canvas.y;
530         evt->flick = FLICK_UNKNOWN;
531 }
532
533 static void lb_mouse_move_cb(void *handle, Evas *e, Evas_Object *obj, void *event_info)
534 {
535         Evas_Event_Mouse_Move *move = event_info;
536         struct event_data *evt;
537
538         evt = evas_object_data_get(obj, "evt");
539         if (!evt)
540                 return;
541
542         if (livebox_lb_type(handle) == LB_TYPE_PIXMAP || livebox_lb_type(handle) == LB_TYPE_BUFFER) {
543                 Evas_Coord x, y, w, h;
544                 double rx, ry;
545
546                 evas_object_geometry_get(obj, &x, &y, &w, &h);
547                 rx = (double)(move->cur.canvas.x - x) / (double)w;
548                 ry = (double)(move->cur.canvas.y - y) / (double)h;
549                 livebox_content_event(handle, LB_MOUSE_MOVE, rx, ry);
550         }
551
552         if ((move->cur.canvas.x - move->prev.canvas.x) > FLICK_COND) {
553                 evt->flick = FLICK_UNKNOWN;
554                 return;
555         } else if ((move->cur.canvas.x - move->prev.canvas.x) < -FLICK_COND) {
556                 evt->flick = FLICK_UNKNOWN;
557                 return;
558         }
559
560         if ((move->cur.canvas.y - move->prev.canvas.y) > 0) {
561                 if (evt->flick != FLICK_DOWN)
562                         evt->flick = FLICK_DOWN;
563         } else if ((move->cur.canvas.y - move->prev.canvas.y) < 0) {
564                 if (evt->flick != FLICK_UP)
565                         evt->flick = FLICK_UP;
566         }
567 }
568
569 static void livebox_added_cb(struct livebox *handle, int ret, void *data)
570 {
571         Evas_Object *layout;
572         Evas_Object *lb_image;
573         Evas_Object *btn;
574         int w;
575         int h;
576         int type;
577         int idx;
578
579         DbgPrint("%s - %d\n", livebox_pkgname(handle), ret);
580
581         if (ret != 0) {
582                 error_popup(data, handle, ret);
583                 return;
584         }
585
586         layout = elm_layout_add(main_get_window());
587         if (!layout) {
588                 ErrPrint("Failed to add a layout\n");
589                 return;
590         }
591
592         if (elm_layout_file_set(layout, PKGROOT "/res/edje/live-viewer.edj", "layout") == EINA_FALSE) {
593                 DbgPrint("Failed to add a layout\n");
594                 evas_object_del(layout);
595                 return;
596         }
597
598         lb_image = create_canvas(layout);
599         if (!lb_image) {
600                 ErrPrint("Failed to create a canvas\n");
601                 evas_object_del(layout);
602                 return;
603         }
604
605         evas_object_event_callback_add(lb_image, EVAS_CALLBACK_MOUSE_UP, lb_mouse_up_cb, handle);
606         evas_object_event_callback_add(lb_image, EVAS_CALLBACK_MOUSE_DOWN, lb_mouse_down_cb, handle);
607         evas_object_event_callback_add(lb_image, EVAS_CALLBACK_MOUSE_MOVE, lb_mouse_move_cb, handle);
608
609         w = 0;
610         h = 0;
611         type = livebox_size(handle);
612         if (type != LB_SIZE_TYPE_UNKNOWN) {
613                 livebox_service_get_size(type, &w, &h);
614                 DbgPrint("%dx%d\n", w, h);
615         }
616         evas_object_resize(lb_image, w, h);
617         evas_object_show(lb_image);
618
619         update_canvas(handle, lb_image);
620
621         btn = elm_button_add(main_get_window());
622         if (btn) {
623                 elm_object_text_set(btn, "Delete");
624                 evas_object_smart_callback_add(btn, "clicked", delete_btn_cb, handle);
625                 elm_object_part_content_set(layout, "delete,btn", btn);
626         }
627
628         elm_object_part_content_set(layout, "livebox", lb_image);
629         evas_object_resize(layout, 720, 1280);
630         evas_object_show(layout);
631
632         create_resize_controller(handle, layout);
633         create_logger(handle, layout);
634
635         livebox_set_data(handle, layout);
636         DbgPrint("Livebox Set Data: %p - %p\n", handle, layout);
637         evas_object_data_set(layout, "sc", data);
638
639         scroller_append(data, layout);
640
641         idx = scroller_get_page_index(data, layout);
642         DbgPrint("Scroll to %d\n", idx);
643         scroller_scroll_to(data, idx);
644 }
645
646 int lb_add(Evas_Object *sc, const char *pkgname)
647 {
648         int w, h;
649         struct livebox *handle;
650
651         evas_object_geometry_get(sc, NULL, NULL, &w, &h);
652
653         DbgPrint("sc: %dx%d, package: %s\n", w, h, pkgname);
654         livebox_activate(pkgname, NULL, NULL);
655
656         handle = livebox_add(pkgname, "default", "user,created", "default",
657                                                 DEFAULT_PERIOD, livebox_added_cb, sc);
658         if (!handle) {
659                 ErrPrint("Failed to add a new livebox\n");
660                 return -EFAULT;
661         }
662
663         return 0;
664 }
665
666 int lb_init(void)
667 {
668         livebox_init(ecore_x_display_get());
669         livebox_set_event_handler(lb_event_cb, NULL);
670         livebox_set_fault_handler(lb_fault_cb, NULL);
671         return 0;
672 }
673
674 int lb_fini(void)
675 {
676         livebox_fini();
677         return 0;
678 }
679
680 /* End of a file */