PUI: fill out missing variables when an ani is created, fix timer stuff
[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("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         if (ani_h->ecore_event_hdls)
349         {
350                 while (eina_array_count(ani_h->ecore_event_hdls))
351                         ecore_event_handler_del(eina_array_pop(ani_h->ecore_event_hdls));
352
353                 eina_array_free(ani_h->ecore_event_hdls);
354                 ani_h->ecore_event_hdls = NULL;
355         }
356 }
357
358 static Eina_Bool
359 _pui_ani_frame_cb(void *data)
360 {
361         Eina_Bool ret;
362
363         pui_ani_t *ani = (pui_ani_t *)data;
364
365         if (!ani)
366         {
367                 pui_err("Invalid pui ani !\n");
368                 return ECORE_CALLBACK_CANCEL;
369         }
370
371         if (!ani->backend_frame_cb)
372         {
373                 pui_err("Invalid backend frame_cb !\n");
374                 return ECORE_CALLBACK_CANCEL;
375         }
376
377         if (!ani->frame_cb_timer)
378         {
379                 pui_err("Invalid frame_cb timer !\n");
380                 return ECORE_CALLBACK_CANCEL;
381         }
382
383         pui_info("frame_cb !\n");
384
385         ret = (Eina_Bool)ani->backend_frame_cb(ani, ++ani->serial);
386
387         pui_ani_status_update(ani, PUI_ANI_STATUS_RUNNING);
388
389         return ret;
390 }
391
392 pui_bool
393 pui_ani_add_frame_cb(pui_ani_t *ani, pui_bool (*frame_cb)(void *data, int serial), double frame_interval)
394 {
395         Ecore_Timer *timer = NULL;
396
397         if (!ani)
398         {
399                 pui_err("Invalid put ani !\n");
400                 return 0;
401         }
402
403         ani->frame_cb = _pui_ani_frame_cb;
404         ani->backend_frame_cb = frame_cb;
405         ani->frame_interval = frame_interval;
406         ani->frame_cb_data = ani;
407         ani->serial = 0;
408
409         timer = ecore_timer_add(frame_interval, _pui_ani_frame_cb, ani);
410
411         if (!timer)
412         {
413                 pui_err("Failed to add ecore timer !\n");
414                 return 0;
415         }
416
417         ani->frame_cb_timer = timer;
418
419         /* call frame_cb for starting the first frame */
420         _pui_ani_frame_cb(ani);
421
422         return 1;
423 }
424
425 void
426 pui_ani_remove_frame_cb(pui_ani_t *ani)
427 {
428         if (!ani)
429                 return;
430
431         if (ani->frame_cb_timer)
432         {
433                 ecore_timer_del(ani->frame_cb_timer);
434                 ani->frame_cb_timer = NULL;
435         }
436
437         ani->frame_cb = NULL;
438         ani->backend_frame_cb = NULL;
439         ani->frame_interval = 0;
440         ani->frame_cb_data = NULL;
441 }
442
443 pui_id
444 pui_ani_get_id(pui_ani_h ani_h)
445 {
446         if (!ani_h || !ani_h->ani)
447                 return NULL;
448
449         return ani_h->ani->id;
450 }
451
452 pui_ani_cmd
453 pui_ani_get_cmd(pui_ani_h ani_h)
454 {
455         if (!ani_h || !ani_h->ani)
456                 return PUI_ANI_CMD_NONE;
457
458         return ani_h->ani->cmd;
459 }
460
461 int
462 pui_ani_get_repeat(pui_ani_h ani_h)
463 {
464         if (!ani_h || !ani_h->ani)
465                 return 0;
466
467         return ani_h->ani->repeat;
468 }
469
470 pui_backend_ani_data *
471 pui_ani_get_ani_data(pui_ani_t *ani)
472 {
473         if (!ani)
474                 return NULL;
475
476         return ani->ani_data;
477 }
478
479 void
480 pui_ani_status_update(pui_ani_t *ani, pui_ani_status status)
481 {
482         //TODO : add PUI EVENT
483
484         ani->status = status;
485 }
486
487 pui_ani_status
488 pui_ani_status_get(pui_ani_t *ani)
489 {
490         pui_ani_status status = PUI_ANI_STATUS_UNKNOWN;
491
492         if (!ani)
493         {
494                 pui_err("Invalid pui ani !\n");
495                 return status;
496         }
497
498         return ani->status;
499 }
500
501 pui_error
502 pui_ani_control(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat)
503 {
504         pui_ani_t *ani = NULL;
505         pui_h handle = NULL;
506         pui_backend_ani_func *ani_func = NULL;
507
508         if (!ani_h)
509                 return PUI_ERROR_INVALID_ANI_HANDLE;
510
511         if (cmd < PUI_ANI_CMD_START || cmd >= PUI_ANI_CMD_LAST)
512         {
513                 pui_err("Invalid cmd ! (repeat=%d)\n", repeat);
514                 return PUI_ERROR_INVALID_ANI_CMD;
515         }
516
517         if (repeat < -1)
518         {
519                 pui_err("Invalid repeat count ! (repeat=%d)\n", repeat);
520                 return PUI_ERROR_INVALID_ANI_REPEAT;
521         }
522
523         //TODO : check if there is any animation being played already
524         //NOTE : the id of the animation being played can be different from ani_h->id
525
526         handle = ani_h->pui_handle;
527         ani = ani_h->ani;
528
529         if (!ani || !ani->ani_data)
530         {
531                 pui_err("Invalid ani or ani_data !\n");
532                 return PUI_ERROR_INTERNAL;
533         }
534
535         ani_func = ani->ani_data->ani_func;
536
537         ani->cmd = cmd;
538         ani->repeat = repeat;
539
540         if (cmd == PUI_ANI_CMD_START)
541         {
542                 ani_func->ani_start(ani, repeat);
543         }
544         else//cmd == PUI_ANI_CMD_STOP
545         {
546                 ani_func->ani_stop(ani);
547                 return PUI_ERROR_NONE;
548         }
549
550         ani_h->frame_done_cb = ecore_wl2_window_frame_callback_add(handle->win, _pui_ani_cb_frame_done, handle);
551
552         if (!ani_h->frame_done_cb)
553         {
554                 pui_err("Failed to add frame callback !");
555                 goto err;
556         }
557
558         //TODO
559
560         return PUI_ERROR_NONE;
561
562 err:
563         return PUI_ERROR_INTERNAL;
564 }
565
566 pui_ani_h
567 pui_ani_create(pui_h handle, pui_id id)
568 {
569         pui_ani_h ani_h = NULL;
570         pui_ani_t *ani = NULL;
571         pui_backend_ani_data *ani_data = NULL;
572
573         if (!handle || !handle->backend_module_data)
574         {
575                 pui_err("Invalid pui handle or backend module data !\n");
576                 return NULL;
577         }
578
579         ani_data = handle->backend_module_data->ani_create(id);
580
581         if (!ani_data)
582         {
583                 pui_err("Invalid ani data from backend module data !\n");
584                 return NULL;
585         }
586
587         ani_h = (pui_ani_h)calloc(1, sizeof(pui_ani));
588
589         if (!ani_h)
590         {
591                 pui_err("Failed to allocate memory for pui ani handle !\n");
592                 goto err;
593         }
594
595         ani_h->id = strdup(id);
596         ani_h->pui_handle = handle;
597         ani_h->ecore_event_hdls = NULL;
598
599         _pui_ani_event_handlers_init(ani_h);
600
601         ani = (pui_ani_t *)calloc(1, sizeof(pui_ani_t));
602
603         if (!ani)
604         {
605                 pui_err("Failed to allocate memory for pui ani mgr !\n");
606                 goto err;
607         }
608
609         ani->ani_h = ani_h;
610         ani->id = id;
611         ani->cmd = PUI_ANI_CMD_NONE;
612         ani->repeat = 0;
613         ani->status = PUI_ANI_STATUS_INITIAL;
614         ani->ani_data = ani_data;
615
616         ani_h->ani = ani;
617
618         handle->ani_handles = eina_list_append(handle->ani_handles, ani_h);
619
620         return ani_h;
621
622 err:
623         if (ani_data)
624         {
625                 handle->backend_module_data->ani_destroy(ani_data);
626         }
627
628         if (ani_h)
629                 free(ani_h);
630
631         return NULL;
632 }
633
634 void
635 pui_ani_destroy(pui_ani_h ani_h)
636 {
637         pui_h handle = NULL;
638         pui_ani_t *ani = NULL;
639         pui_backend_module_data *backend_module_data = NULL;
640
641         if (!ani_h || !ani_h->pui_handle)
642                 return;
643
644         handle = ani_h->pui_handle;
645         ani = ani_h->ani;
646
647         /* stop the animation being played already if any */
648         if (ani->status != PUI_ANI_STATUS_STOPPED)
649                 pui_ani_control(ani_h, PUI_ANI_CMD_STOP, 0);
650
651         backend_module_data = handle->backend_module_data;
652         backend_module_data->ani_destroy(ani->ani_data);
653         ani->ani_data = NULL;
654
655         if (ani->frame_cb_timer)
656         {
657                 ecore_timer_del(ani->frame_cb_timer);
658                 ani->frame_cb_timer = NULL;
659         }
660
661         free(ani_h->ani);
662
663         _pui_ani_event_handlers_shutdown(ani_h);
664
665         if (ani_h->frame_done_cb)
666         {
667                 ecore_wl2_window_frame_callback_del(ani_h->frame_done_cb);
668                 ani_h->frame_done_cb = NULL;
669         }
670
671         handle->ani_handles = eina_list_remove(handle->ani_handles, ani_h);
672
673         free(ani_h->id);
674         free(ani_h);
675 }
676