renew pui prototype again
[platform/core/uifw/libpui.git] / src / PUI_ani.c
1 #include "PUI_internal.h"
2 #include "PUI_backend.h"
3 #include "PUI.h"
4 #include <Eina.h>
5
6 static int KEY_WL_BUFFER = 0xabcdbeaf;
7 static int KEY_CLIENT = 0xdcbabeaf;
8
9 static Eina_Bool
10 _cb_window_show(void *data, int type EINA_UNUSED, void *event)
11 {
12         pui_ani_h handle =  (pui_ani_h)data;
13         Ecore_Wl2_Event_Window_Show *ev = (Ecore_Wl2_Event_Window_Show *)event;
14
15         pui_info("...\n");
16
17         /* TODO */
18         (void) handle;
19         (void) ev;
20
21         return ECORE_CALLBACK_PASS_ON;
22 }
23
24 static Eina_Bool
25 _cb_focus_in(void *data, int type EINA_UNUSED, void *event)
26 {
27         pui_ani_h handle =  (pui_ani_h)data;
28         Ecore_Wl2_Event_Focus_In *ev = (Ecore_Wl2_Event_Focus_In *)event;
29
30         pui_info("...\n");
31
32         /* TODO */
33         (void) handle;
34         (void) ev;
35
36         return ECORE_CALLBACK_PASS_ON;
37 }
38
39 static Eina_Bool
40 _cb_focus_out(void *data, int type EINA_UNUSED, void *event)
41 {
42         pui_ani_h handle =  (pui_ani_h)data;
43         Ecore_Wl2_Event_Focus_Out *ev = (Ecore_Wl2_Event_Focus_Out *)event;
44
45         pui_info("...\n");
46
47         /* TODO */
48         (void) handle;
49         (void) ev;
50
51         return ECORE_CALLBACK_PASS_ON;
52 }
53
54 static Eina_Bool
55 _cb_visibility_change(void *data, int type EINA_UNUSED, void *event)
56 {
57         pui_ani_h ani_h =  (pui_ani_h)data;
58         pui_ani_t *ani = ani_h->ani;
59         pui_h ph = ani_h->pui_handle;
60
61         Ecore_Wl2_Event_Window_Visibility_Change *ev;
62         PUI_Event_Animation_Status *e = NULL;
63
64         ev = event;
65
66         pui_info("Visibility change (window=0x%x, fully_obscured=%d)\n", ev->win, ev->fully_obscured);
67
68         /* check if this is needed */
69         ph->visibility = !(ev->fully_obscured);
70
71         if (ev->fully_obscured)
72         {
73                 if (ani->status == PUI_ANI_STATUS_RUNNING)
74                 {
75                         ani->status = PUI_ANI_STATUS_STOPPED;
76
77                         e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
78
79                         if (!e)
80                         {
81                                 pui_err("Failed to allocate memory for PUI Event !\n");
82                                 return ECORE_CALLBACK_PASS_ON;
83                         }
84                         
85                         e->win = ev->win;
86                         e->status = PUI_ANI_STATUS_FORCE_STOPPED;
87                         
88                         ecore_event_add(PUI_EVENT_ANI_STOPPED, e, NULL, ani_h);
89                 }
90         }
91         else
92         {
93                 e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
94                 
95                 if (!e)
96                 {
97                         pui_err("Failed to allocate memory for PUI Event !\n");
98                         return ECORE_CALLBACK_PASS_ON;
99                 }
100                 
101                 e->win = ev->win;
102                 e->status = ani->status;
103                 
104                 if (ani->status == PUI_ANI_STATUS_STOPPED)
105                         ecore_event_add(PUI_EVENT_ANI_READY_TO_START, e, NULL, ani_h);
106                 else if(ani->status == PUI_ANI_STATUS_PAUSED)
107                         ecore_event_add(PUI_EVENT_ANI_READY_TO_RESUME, e, NULL, ani_h);
108         }
109
110         return ECORE_CALLBACK_PASS_ON;
111 }
112
113 static void
114 _pui_ani_cb_frame_done(Ecore_Wl2_Window *win, uint32_t timestamp EINA_UNUSED, void *data)
115 {
116         pui_h handle = (pui_h) data;
117
118         pui_info("Frame done ! (window=%p)\n", win);
119
120         // TODO
121         (void) handle;
122
123         return;
124 }
125
126 static void
127 _buffer_release(void *data, struct wl_buffer *buffer)
128 {
129         tbm_surface_h surface = (tbm_surface_h)data;
130         pui_h handle;
131
132         tbm_surface_internal_get_user_data(surface, (unsigned long)&KEY_CLIENT, (void **)&handle);
133         tbm_surface_queue_release(handle->tbm_queue, surface);
134
135         pui_info("[UPDATE] release wl_buffer:%p, surface:%p\n", buffer, surface);
136 }
137
138 static const struct wl_buffer_listener buffer_listener = {
139     _buffer_release
140 };
141
142 pui_ani_control_buffer *
143 pui_ani_get_buffer(pui_ani_h ani_h)
144 {
145         pui_h handle = NULL;
146         tbm_surface_error_e ret;
147         tbm_surface_h surface;
148         pui_ani_control_buffer *buffer = NULL;
149
150         if (!ani_h)
151         {
152                 pui_err(\r"Invalid pui ani handle !\n");
153                 return NULL;
154         }
155
156         handle = ani_h->pui_handle;
157
158         if (!handle)
159         {
160                 pui_err("Error : PUI_INT_ERROR_INVALID_HANDLE\n");
161                 return NULL;
162         }
163
164         if (handle->current_surface)
165         {
166                 pui_warn("Current_surface is not used !\n");
167         }
168
169         if (!tbm_surface_queue_can_dequeue(handle->tbm_queue, 0))
170         {
171                 pui_err("[UPDATE] Cannot dequeue (error : PUI_ERROR_INTERNAL)\n");
172                 return NULL;
173         }
174
175         ret = tbm_surface_queue_dequeue(handle->tbm_queue, &surface);
176
177         if (ret != TBM_SURFACE_ERROR_NONE)
178         {
179                 pui_err("[UPDATE] dequeue err:%d\n", ret);
180                 return NULL;
181         }
182
183         tbm_surface_map(surface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &handle->current_sinfo);
184
185         handle->current_surface = surface;
186         buffer = (pui_ani_control_buffer *)&(handle->current_sinfo.planes[0]);
187
188         return buffer;
189 }
190
191 pui_int_error
192 pui_ani_set_buffer(pui_ani_h ani_h, pui_ani_control_buffer *buffer)
193 {
194         pui_h handle = NULL;
195
196         if (!ani_h)
197         {
198                 pui_err("Invalid ani handle !\n");
199                 return PUI_INT_ERROR_INVALID_HANDLE;
200         }
201
202         handle = ani_h->pui_handle;
203
204         if (!handle)
205         {
206                 pui_err("Error : PUI_INT_ERROR_INVALID_HANDLE\n");
207                 return PUI_INT_ERROR_INVALID_HANDLE;
208         }
209
210         if (!handle->current_surface)
211         {
212                 pui_err("Current_surface is not valid !\n");
213                 return PUI_INT_ERROR_INVALID_SURFACE;
214         }
215
216         if (!buffer || !buffer->ptr || !buffer->size)
217                 return PUI_INT_ERROR_INVALID_BUFFER;
218
219         handle->is_buffer_set = 1;
220
221         return PUI_INT_ERROR_NONE;
222 }
223
224 pui_int_error
225 pui_ani_update(pui_ani_h ani_h)
226 {
227         tbm_surface_h surface;
228         tbm_surface_error_e ret;
229         struct wl_buffer *wl_buffer = NULL;
230
231         pui_h handle = NULL;
232
233         if (!ani_h)
234         {
235                 pui_err("Invalid ani handle !\n");
236                 return PUI_INT_ERROR_INVALID_HANDLE;
237         }
238
239         handle = ani_h->pui_handle;
240
241         if (!handle)
242         {
243                 pui_err("Error : PUI_INT_ERROR_INVALID_HANDLE\n");
244                 return PUI_INT_ERROR_INVALID_HANDLE;
245         }
246
247         if (!handle->current_surface)
248                 return PUI_INT_ERROR_INVALID_SURFACE;
249
250         if (!handle->is_buffer_set)
251         {
252                 pui_err("Buffer is not set !\n");
253                 return PUI_INT_ERROR_INVALID_BUFFER;
254         }
255
256         surface = handle->current_surface;
257         handle->current_surface = NULL;
258
259         tbm_surface_unmap(surface);
260
261         ret = tbm_surface_queue_enqueue(handle->tbm_queue, surface);
262
263         if (ret != TBM_SURFACE_ERROR_NONE)
264         {
265                 pui_err("[UPDATE] enqueue err:%d\n", ret);
266                 return PUI_INT_ERROR_INVALID_SURFACE;
267         }
268
269         ret = tbm_surface_queue_acquire(handle->tbm_queue, &surface);
270
271         if (ret != TBM_SURFACE_ERROR_NONE)
272         {
273                 pui_err("[UPDATE] acquire err:%d\n", ret);
274                 return PUI_INT_ERROR_INVALID_SURFACE;
275         }
276
277         if (!tbm_surface_internal_get_user_data(surface, (unsigned long)&KEY_WL_BUFFER, (void **)&wl_buffer)) {
278                 wl_buffer = wayland_tbm_client_create_buffer(handle->wl_tbm_client, surface);
279
280                 if (!wl_buffer)
281                 {
282                         pui_err("[UPDATE] failed to create wl_buffer tbm_surface:%p\n", surface);
283                         return PUI_INT_ERROR_INVALID_BUFFER;
284                 }
285
286                 wl_buffer_add_listener(wl_buffer, &buffer_listener, surface);
287
288                 tbm_surface_internal_add_user_data(surface, (unsigned long)&KEY_WL_BUFFER, NULL);
289                 tbm_surface_internal_set_user_data(surface, (unsigned long)&KEY_WL_BUFFER, wl_buffer);
290                 tbm_surface_internal_add_user_data(surface, (unsigned long)&KEY_CLIENT, NULL);
291                 tbm_surface_internal_set_user_data(surface, (unsigned long)&KEY_CLIENT, handle);
292         }
293
294         if (!wl_buffer)
295         {
296                 pui_err("[UPDATE] dequeue err:%d\n", ret);
297                 return PUI_INT_ERROR_INVALID_BUFFER;
298         }
299
300         ecore_wl2_window_buffer_attach(handle->win, wl_buffer, 0, 0, 0);
301         ecore_wl2_window_damage(handle->win, NULL, 0);
302         ecore_wl2_window_commit(handle->win, EINA_TRUE);
303
304         pui_info("[UPDATE] commit wl_buffer:%p, surface:%p\n", wl_buffer, surface);
305
306         handle->is_buffer_set = 0;
307
308         return PUI_INT_ERROR_NONE;
309 }
310
311 static void
312 _pui_ani_event_handlers_init(pui_ani_h ani_h)
313 {
314         Ecore_Event_Handler *h = NULL;
315
316         if (!ani_h)
317         {
318                 pui_err("Invalid handle !\n");
319                 return;
320         }
321
322         if (!ani_h->ecore_event_hdls)
323                 ani_h->ecore_event_hdls = eina_array_new(5);
324
325         h = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_SHOW, _cb_window_show, ani_h);
326         eina_array_push(ani_h->ecore_event_hdls, h);
327
328         h = ecore_event_handler_add(ECORE_WL2_EVENT_FOCUS_IN, _cb_focus_in, ani_h);
329         eina_array_push(ani_h->ecore_event_hdls, h);
330
331         h = ecore_event_handler_add(ECORE_WL2_EVENT_FOCUS_OUT, _cb_focus_out, ani_h);
332         eina_array_push(ani_h->ecore_event_hdls, h);
333
334         h = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, _cb_visibility_change, ani_h);
335         eina_array_push(ani_h->ecore_event_hdls, h);
336
337 }
338
339 static void
340 _pui_ani_event_handlers_shutdown(pui_ani_h ani_h)
341 {
342         if (!ani_h)
343         {
344                 pui_err("Invalid handle !\n");
345                 return;
346         }
347
348         while (eina_array_count(ani_h->ecore_event_hdls))
349                 ecore_event_handler_del(eina_array_pop(ani_h->ecore_event_hdls));
350         eina_array_free(ani_h->ecore_event_hdls);
351
352         ani_h->ecore_event_hdls = NULL;
353 }
354
355 Eina_Bool _pui_ani_frame_cb(void *data)
356 {
357         Eina_Bool ret;
358
359         pui_ani_t *ani = (pui_ani_t *)data;
360
361         if (!ani)
362         {
363                 pui_err("Invalid pui ani !\n");
364                 return ECORE_CALLBACK_CANCEL;
365         }
366
367         if (!ani->backend_frame_cb)
368         {
369                 pui_err("Invalid backend frame_cb !\n");
370                 return ECORE_CALLBACK_CANCEL;
371         }
372
373         pui_info("frame_cb !\n");
374
375         ret = (Eina_Bool)ani->backend_frame_cb(ani, ++ani->serial);
376
377         if (!ani->frame_cb_timer)
378                 return ECORE_CALLBACK_CANCEL;
379
380         pui_ani_status_update(ani, PUI_ANI_STATUS_RUNNING);
381
382         return ret;
383 }
384
385 void
386 pui_ani_add_frame_cb(pui_ani_t *ani, pui_bool (*frame_cb)(void *data, int serial), double frame_interval)
387 {
388         Ecore_Timer *timer = NULL;
389
390         if (!ani)
391         {
392                 pui_err("Invalid put ani !\n");
393                 return;
394         }
395
396         ani->frame_cb = _pui_ani_frame_cb;
397         ani->backend_frame_cb = frame_cb;
398         ani->frame_interval = frame_interval;
399         ani->frame_cb_data = ani;
400         ani->serial = 0;
401
402         timer = ecore_timer_add(frame_interval, (Ecore_Task_Cb)ani->frame_cb, ani->frame_cb_data);
403
404         if (ani->frame_cb_timer)
405         {
406                 ecore_timer_del(ani->frame_cb_timer);
407                 ani->frame_cb_timer = NULL;
408         }
409
410         ani->frame_cb_timer = timer;
411
412         /* call frame_cb for starting the first frame */
413         _pui_ani_frame_cb(ani);
414 }
415
416 void
417 pui_ani_remove_frame_cb(pui_ani_t *ani)
418 {
419         if (!ani)
420                 return;
421
422         if (ani->frame_cb_timer)
423         {
424                 ecore_timer_del(ani->frame_cb_timer);
425                 ani->frame_cb_timer = NULL;
426         }
427
428         ani->frame_cb = NULL;
429         ani->backend_frame_cb = NULL;
430         ani->frame_interval = 0;
431         ani->frame_cb_data = NULL;
432 }
433
434 pui_id
435 pui_ani_get_id(pui_ani_h ani_h)
436 {
437         if (!ani_h || !ani_h->ani)
438                 return NULL;
439
440         return ani_h->ani->id;
441 }
442
443 pui_ani_cmd
444 pui_ani_get_cmd(pui_ani_h ani_h)
445 {
446         if (!ani_h || !ani_h->ani)
447                 return PUI_ANI_CMD_NONE;
448
449         return ani_h->ani->cmd;
450 }
451
452 int
453 pui_ani_get_repeat(pui_ani_h ani_h)
454 {
455         if (!ani_h || !ani_h->ani)
456                 return 0;
457
458         return ani_h->ani->repeat;
459 }
460
461 pui_backend_ani_data *
462 pui_ani_get_ani_data(pui_ani_t *ani)
463 {
464         if (!ani)
465                 return NULL;
466
467         return ani->ani_data;
468 }
469
470 void
471 pui_ani_status_update(pui_ani_t *ani, pui_ani_status status)
472 {
473         //TODO : add PUI EVENT
474
475         ani->status = status;
476 }
477
478 pui_ani_status
479 pui_ani_status_get(pui_ani_t *ani)
480 {
481         pui_ani_status status = PUI_ANI_STATUS_UNKNOWN;
482
483         if (!ani)
484         {
485                 pui_err("Invalid pui ani !\n");
486                 return status;
487         }
488
489         return ani->status;
490 }
491
492 pui_error
493 pui_ani_control(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat)
494 {
495         pui_ani_t *ani = NULL;
496         pui_h handle = NULL;
497         pui_backend_ani_func *ani_func = NULL;
498
499         if (!ani_h)
500                 return PUI_ERROR_INVALID_ANI_HANDLE;
501
502         if (cmd < PUI_ANI_CMD_START || cmd >= PUI_ANI_CMD_LAST)
503         {
504                 pui_err("Invalid cmd ! (repeat=%d)\n", repeat);
505                 return PUI_ERROR_INVALID_ANI_CMD;
506         }
507
508         if (repeat < -1)
509         {
510                 pui_err("Invalid repeat count ! (repeat=%d)\n", repeat);
511                 return PUI_ERROR_INVALID_ANI_REPEAT;
512         }
513
514         //TODO : check if there is any animation being played already
515         //NOTE : the id of the animation being played can be different from ani_h->id
516
517         handle = ani_h->pui_handle;
518         ani = ani_h->ani;
519
520         if (!ani || !ani->ani_data)
521         {
522                 pui_err("Invalid ani or ani_data !\n");
523                 return PUI_ERROR_INTERNAL;
524         }
525
526         ani_func = ani->ani_data->ani_func;
527
528         if (cmd == PUI_ANI_CMD_START)
529         {
530                 ani_func->ani_start(ani, repeat);
531         }
532         else//cmd == PUI_ANI_CMD_STOP
533         {
534                 ani_func->ani_stop(ani);
535         }
536
537         ani->cmd = cmd;
538         ani->repeat = repeat;
539
540         ani_h->frame_done_cb = ecore_wl2_window_frame_callback_add(handle->win, _pui_ani_cb_frame_done, handle);
541
542         if (!ani_h->frame_done_cb)
543         {
544                 pui_err("Failed to add frame callback !");
545                 goto err;
546         }
547
548         //TODO
549
550         return PUI_ERROR_NONE;
551
552 err:
553         return PUI_ERROR_INTERNAL;
554 }
555
556 pui_ani_h
557 pui_ani_create(pui_h handle, pui_id id)
558 {
559         pui_ani_h ani_h = NULL;
560         pui_ani_t *ani = NULL;
561         pui_backend_ani_data *ani_data = NULL;
562
563         if (!handle || !handle->backend_module_data)
564         {
565                 pui_err("Invalid pui handle or backend module data !\n");
566                 return NULL;
567         }
568
569         ani_data = handle->backend_module_data->ani_create(id);
570
571         if (!ani_data)
572         {
573                 pui_err("Invalid ani data from backend module data !\n");
574                 return NULL;
575         }
576
577         ani_h = (pui_ani_h)calloc(1, sizeof(pui_ani_h));
578
579         if (!ani_h)
580         {
581                 pui_err("Failed to allocate memory for pui ani handle !\n");
582                 goto err;
583         }
584
585         ani_h->ecore_event_hdls = NULL;
586         _pui_ani_event_handlers_init(ani_h);
587
588         ani = (pui_ani_t *)calloc(1, sizeof(pui_ani_t));
589
590         if (!ani)
591         {
592                 pui_err("Failed to allocate memory for pui ani mgr !\n");
593                 goto err;
594         }
595
596         ani->ani_h = ani_h;
597         ani->id = id;
598         ani->status = PUI_ANI_STATUS_INITIAL;
599         ani->ani_data = ani_data;
600
601         handle->ani_handles = eina_list_append(handle->ani_handles, ani_h);
602
603         return ani_h;
604
605 err:
606         if (ani_data)
607         {
608                 handle->backend_module_data->ani_destroy(ani_data);
609         }
610
611         if (ani_h)
612                 free(ani_h);
613
614         return NULL;
615 }
616
617 void
618 pui_ani_destroy(pui_ani_h ani_h)
619 {
620         pui_h handle = NULL;
621         pui_ani_t *ani = NULL;
622         pui_backend_module_data *backend_module_data = NULL;
623
624         if (!ani_h || !ani_h->pui_handle)
625                 return;
626
627         handle = ani_h->pui_handle;
628         ani = ani_h->ani;
629
630         /* stop the animation being played already if any */
631         if (ani->status != PUI_ANI_STATUS_STOPPED)
632                 pui_ani_control(ani_h, PUI_ANI_CMD_STOP, 0);
633
634         backend_module_data = handle->backend_module_data;
635         backend_module_data->ani_destroy(ani->ani_data);
636         ani->ani_data = NULL;
637
638         if (ani->frame_cb_timer)
639         {
640                 ecore_timer_del(ani->frame_cb_timer);
641                 ani->frame_cb_timer = NULL;
642         }
643
644         free(ani_h->ani);
645
646         _pui_ani_event_handlers_shutdown(ani_h);
647         
648         if (ani_h->frame_done_cb)
649         {
650                 ecore_wl2_window_frame_callback_del(ani_h->frame_done_cb);
651                 ani_h->frame_done_cb = NULL;
652         }
653
654         handle->ani_handles = eina_list_remove(handle->ani_handles, ani_h);
655
656         free(ani_h);
657 }
658