default_backend : remove unused variable and change variables as static
[platform/core/uifw/libpui.git] / src / PUI_ani.c
1 /*
2  * Copyright © 2019 Samsung Electronics co., Ltd. All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial
14  * portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25
26 #include "PUI_internal.h"
27 #include "PUI_backend.h"
28 #include "PUI.h"
29 #include <Eina.h>
30
31 pui_int_error
32 _pui_ani_error_to_int_error(pui_error e)
33 {
34         pui_int_error ei;
35
36         switch (e)
37         {
38                 case PUI_ERROR_NONE:
39                         ei = PUI_INT_ERROR_NONE;
40                         break;
41
42                 case PUI_ERROR_INVALID_HANDLE:
43                         ei = PUI_INT_ERROR_INVALID_HANDLE;
44                         break;
45
46                 case PUI_ERROR_INVALID_SURFACE:
47                         ei = PUI_INT_ERROR_INVALID_SURFACE;
48                         break;
49
50                 case PUI_ERROR_INVALID_BUFFER:
51                         ei = PUI_INT_ERROR_INVALID_BUFFER;
52                         break;
53
54                 default:
55                         ei = PUI_INT_ERROR_UNKNOWN;
56                         break;
57         }
58
59         return ei;
60 }
61
62 static void
63 _pui_ani_cb_frame_done(Ecore_Wl2_Window *win, uint32_t timestamp EINA_UNUSED, void *data)
64 {
65         pui_h handle = (pui_h) data;
66
67         pui_info("Frame done ! (window=0x%x)\n", ecore_wl2_window_id_get(win));
68
69         /* TODO : make use of handle */
70         (void) handle;
71
72         return;
73 }
74
75 pui_ani_control_buffer *
76 pui_ani_get_last_buffer(pui_ani_h ani_h)
77 {
78         pui_h handle = NULL;
79         pui_ani_control_buffer *buffer = NULL;
80
81         if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
82         {
83                 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
84                 return NULL;
85         }
86
87         handle = ani_h->pui_handle;
88         buffer = pui_display_get_last_buffer(handle);
89
90         return buffer;
91 }
92
93 pui_ani_control_buffer *
94 pui_ani_get_buffer(pui_ani_h ani_h)
95 {
96         pui_h handle = NULL;
97         pui_ani_control_buffer *buffer = NULL;
98
99         if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
100         {
101                 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
102                 return NULL;
103         }
104
105         handle = ani_h->pui_handle;
106         buffer = pui_display_get_buffer(handle);
107
108         return buffer;
109 }
110
111 pui_int_error
112 pui_ani_set_buffer(pui_ani_h ani_h, pui_ani_control_buffer *buffer)
113 {
114         pui_error e = PUI_ERROR_NONE;
115         pui_h handle = NULL;
116
117         if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
118         {
119                 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
120                 return PUI_ERROR_INVALID_HANDLE;
121         }
122
123         handle = ani_h->pui_handle;
124
125         if (!PUI_MAGIC_CHECK(handle, PUI_MAGIC_PUI_H))
126         {
127                 PUI_MAGIC_FAIL(handle, PUI_MAGIC_PUI_H, __FUNCTION__);
128                 return PUI_ERROR_INVALID_HANDLE;
129         }
130
131         e = pui_display_set_buffer(handle, buffer);
132
133         return _pui_ani_error_to_int_error(e);
134 }
135
136 pui_int_error
137 pui_ani_update(pui_ani_h ani_h)
138 {
139         pui_error e = PUI_ERROR_NONE;
140         pui_h handle = NULL;
141
142         if (!ani_h)
143         {
144                 pui_err("Invalid ani handle !\n");
145                 return PUI_INT_ERROR_INVALID_HANDLE;
146         }
147
148         handle = ani_h->pui_handle;
149         e = pui_display_update(handle);
150
151         return _pui_ani_error_to_int_error(e);
152 }
153
154 static Eina_Bool
155 _pui_ani_frame_cb(void *data)
156 {
157         Eina_Bool ret;
158         pui_ani_t *ani = (pui_ani_t *)data;
159
160         if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
161         {
162                 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
163                 return ECORE_CALLBACK_CANCEL;
164         }
165
166         if (!ani->backend_frame_cb)
167         {
168                 pui_err("Invalid backend frame_cb !\n");
169                 return ECORE_CALLBACK_CANCEL;
170         }
171
172         if (!ani->frame_cb_timer)
173         {
174                 pui_err("Invalid frame_cb timer !\n");
175                 return ECORE_CALLBACK_CANCEL;
176         }
177
178         pui_info("...\n");
179
180         ret = (Eina_Bool)ani->backend_frame_cb(ani, ++ani->serial);
181
182         if (!ret)
183         {
184                 pui_err("Failed on backend's frame_cb !Frame_cb will be removed forcefuly !\n");
185
186                 pui_ani_remove_frame_cb(ani);
187
188                 return EINA_FALSE;
189         }
190
191         if (ret && PUI_ANI_STATUS_STARTED == ani->status)
192                 pui_ani_status_update(ani, PUI_ANI_STATUS_RUNNING);
193
194         return ECORE_CALLBACK_RENEW;
195 }
196
197 pui_bool
198 pui_ani_add_frame_cb(pui_ani_t *ani, pui_bool (*frame_cb)(void *data, int serial), double frame_interval)
199 {
200         Ecore_Timer *timer = NULL;
201
202         if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
203         {
204                 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
205                 return 0;
206         }
207
208         if (frame_interval <= 0.0f)
209         {
210                 pui_err("Invalid frame interval (%.2f) ! frame interval must be larger than 0.\n", frame_interval);
211                 return 0;
212         }
213
214         ani->frame_cb = _pui_ani_frame_cb;
215         ani->backend_frame_cb = frame_cb;
216         ani->frame_interval = frame_interval;
217         ani->frame_cb_data = ani;
218         ani->serial = 0;
219
220         timer = ecore_timer_add(frame_interval, _pui_ani_frame_cb, ani);
221
222         if (!timer)
223         {
224                 pui_err("Failed to add ecore timer !\n");
225                 return 0;
226         }
227
228         ani->frame_cb_timer = timer;
229
230         pui_info("[Frame callback added][ani id=%s] frame_interval=%.2f\n", ani->id, frame_interval);
231
232         /* call frame_cb for starting the first frame */
233         _pui_ani_frame_cb(ani);
234
235         return 1;
236 }
237
238 void
239 pui_ani_remove_frame_cb(pui_ani_t *ani)
240 {
241         if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
242         {
243                 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
244                 return;
245         }
246
247         if (ani->frame_cb_timer)
248         {
249                 ecore_timer_del(ani->frame_cb_timer);
250                 ani->frame_cb_timer = NULL;
251         }
252
253         ani->frame_cb = NULL;
254         ani->backend_frame_cb = NULL;
255         ani->frame_interval = 0;
256         ani->frame_cb_data = NULL;
257
258         pui_info("[Frame callback removed][ani id=%s]\n", ani->id);
259 }
260
261 pui_id
262 pui_ani_get_id(pui_ani_h ani_h)
263 {
264         if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
265         {
266                 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
267                 return NULL;
268         }
269
270         if (!PUI_MAGIC_CHECK(ani_h->ani, PUI_MAGIC_ANI_T))
271         {
272                 PUI_MAGIC_FAIL(ani_h->ani, PUI_MAGIC_ANI_T, __FUNCTION__);
273                 return NULL;
274         }
275
276         return ani_h->ani->id;
277 }
278
279 pui_ani_cmd
280 pui_ani_get_cmd(pui_ani_h ani_h)
281 {
282         if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
283         {
284                 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
285                 return PUI_ANI_CMD_NONE;
286         }
287
288         if (!PUI_MAGIC_CHECK(ani_h->ani, PUI_MAGIC_ANI_T))
289         {
290                 PUI_MAGIC_FAIL(ani_h->ani, PUI_MAGIC_ANI_T, __FUNCTION__);
291                 return PUI_ANI_CMD_NONE;
292         }
293
294         return ani_h->ani->cmd;
295 }
296
297 int
298 pui_ani_get_repeat(pui_ani_h ani_h)
299 {
300         if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
301         {
302                 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
303                 return 0;
304         }
305
306         if (!PUI_MAGIC_CHECK(ani_h->ani, PUI_MAGIC_ANI_T))
307         {
308                 PUI_MAGIC_FAIL(ani_h->ani, PUI_MAGIC_ANI_T, __FUNCTION__);
309                 return 0;
310         }
311
312         return ani_h->ani->repeat;
313 }
314
315 pui_backend_ani_data *
316 pui_ani_get_ani_data(pui_ani_t *ani)
317 {
318         if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
319         {
320                 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
321                 return NULL;
322         }
323
324         return ani->ani_data;
325 }
326
327 void
328 pui_ani_status_update(pui_ani_t *ani, pui_ani_status status)
329 {
330         int ev_type = -1;
331         pui_ani_h ani_h;
332         PUI_Event_Animation_Status *e = NULL;
333
334         if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
335         {
336                 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
337                 return;
338         }
339
340         if (ani->status == status)
341                 return;
342
343         ani_h = ani->ani_h;
344
345         ani->status = status;
346
347         switch (status)
348         {
349                 case PUI_ANI_STATUS_STARTED:
350                         ev_type = PUI_EVENT_ANI_STARTED;
351                         pui_info("[Status update][ani id:%s] PUI_EVENT_ANI_STARTED event has been added.\n", ani->id);
352                         break;
353
354                 case PUI_ANI_STATUS_RUNNING:
355                         pui_info("[Status update][ani id:%s] PUI_ANI_STATUS_RUNNING !\n", ani->id);
356                         break;
357
358                 case PUI_ANI_STATUS_PAUSED:
359                         ev_type = PUI_EVENT_ANI_PAUSED;
360                         pui_info("[Status update][ani id:%s] PUI_EVENT_ANI_PAUSED event has been added.\n", ani->id);
361                         break;
362
363                 case PUI_ANI_STATUS_STOPPED:
364                         ev_type = PUI_EVENT_ANI_STOPPED;
365                         pui_info("[Status update][ani id:%s] PUI_EVENT_ANI_STOPPED event has been added.\n", ani->id);
366                         break;
367
368                 default:
369                         pui_err("Unknown status !(ani status=%d, id=%s) !\n", status, ani->id);
370                         return;
371         }
372
373         if (ev_type > 0)
374         {
375                 e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
376
377                 if (!e)
378                 {
379                         pui_err("Failed to allocate memory for PUI Event !\n");
380                         return;
381                 }
382
383                 e->ani_h = ani_h;
384                 e->win = ecore_wl2_window_id_get(ani_h->pui_handle->win);
385                 e->status = status;
386
387                 ecore_event_add(ev_type, e, NULL, ani_h);
388         }
389 }
390
391 pui_ani_status
392 pui_ani_status_get(pui_ani_t *ani)
393 {
394         pui_ani_status status = PUI_ANI_STATUS_UNKNOWN;
395
396         if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
397         {
398                 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
399                 return status;
400         }
401
402         return ani->status;
403 }
404
405 static pui_error
406 _pui_ani_control_with_force(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat, pui_bool force)
407 {
408         pui_int_error ei = PUI_INT_ERROR_NONE;
409         pui_ani_t *ani = NULL;
410         pui_h handle = NULL;
411         pui_backend_ani_func *ani_func = NULL;
412
413         if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
414         {
415                 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
416                 return PUI_ERROR_INVALID_ANI_HANDLE;
417         }
418
419         if (cmd < PUI_ANI_CMD_START || cmd >= PUI_ANI_CMD_LAST)
420         {
421                 pui_err("Invalid cmd ! (cmd=%d)\n", cmd);
422                 return PUI_ERROR_INVALID_ANI_CMD;
423         }
424
425         if (repeat < -1)
426         {
427                 pui_err("Invalid repeat count ! (repeat=%d)\n", repeat);
428                 return PUI_ERROR_INVALID_ANI_REPEAT;
429         }
430
431         handle = ani_h->pui_handle;
432         ani = ani_h->ani;
433
434         if (!PUI_MAGIC_CHECK(handle, PUI_MAGIC_PUI_H))
435         {
436                 PUI_MAGIC_FAIL(handle, PUI_MAGIC_PUI_H, __FUNCTION__);
437                 return PUI_ERROR_INTERNAL;
438         }
439
440         if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
441         {
442                 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
443                 return PUI_ERROR_INTERNAL;
444         }
445
446         if (!ani->ani_data)
447         {
448                 pui_err("Invalid ani_data !\n");
449                 return PUI_ERROR_INTERNAL;
450         }
451
452         ani_func = ani->ani_data->ani_func;
453
454         ani->cmd = cmd;
455         ani->repeat = repeat;
456
457         if (cmd == PUI_ANI_CMD_START)
458         {
459                 if (handle->manual_render)
460                 {
461                         pui_err("Manual render has been set ! Unable to start animation.\n");
462                         return PUI_ERROR_MANUAL_RENDER_ENABLED;
463                 }
464
465                 if (handle->current_ani_h && handle->current_ani_h != ani_h)
466                 {
467                         pui_ani_t *current_ani = handle->current_ani_h->ani;
468
469                         if (current_ani->status >= PUI_ANI_STATUS_STARTED &&
470                                 current_ani->status <= PUI_ANI_STATUS_RUNNING)
471                         {
472                                 pui_info("current_ani id=%s, status=%d\n", current_ani->id, current_ani->status);
473
474                                 ei = _pui_ani_control_with_force(handle->current_ani_h, PUI_ANI_CMD_STOP, 0, force);
475
476                                 if (ei != PUI_INT_ERROR_NONE)
477                                         pui_info("Failed to stop running previous animation ! (id:%s)\n", current_ani->id);
478
479                                 current_ani = NULL;
480                                 handle->current_ani_h = NULL;
481                         }
482                 }
483
484                 ei = ani_func->ani_start(ani, repeat);
485
486                 if (ei != PUI_INT_ERROR_NONE)
487                 {
488                         pui_err("Error on starting animation ! (id:%s, repeat:%d, status=%d))\n", ani->id, repeat, ani->status);
489
490                         if (ani->status != PUI_ANI_STATUS_RUNNING)
491                                 _pui_ani_control_with_force(ani_h, PUI_ANI_CMD_STOP, 0, 0);
492
493                         return PUI_ERROR_INTERNAL;
494                 }
495
496                 handle->current_ani_h = ani_h;
497         }
498         else//cmd == PUI_ANI_CMD_STOP
499         {
500                 ei = ani_func->ani_stop(ani, force);
501
502                 if (ani->frame_cb_timer)
503                         pui_ani_remove_frame_cb(ani);
504
505                 if (ei != PUI_INT_ERROR_NONE)
506                 {
507                         pui_err("Failied on stopping animation ! (id:%s)\n", ani->id);
508
509                         if (ani->status != PUI_ANI_STATUS_STOPPED)
510                                 pui_ani_status_update(ani, PUI_ANI_STATUS_STOPPED);
511
512                         return PUI_ERROR_INTERNAL;
513                 }
514
515                 return PUI_ERROR_NONE;
516         }
517
518         ani_h->frame_done_cb = ecore_wl2_window_frame_callback_add(handle->win, _pui_ani_cb_frame_done, handle);
519
520         if (!ani_h->frame_done_cb)
521         {
522                 pui_err("Failed to add frame callback !");
523                 goto err;
524         }
525
526         return PUI_ERROR_NONE;
527
528 err:
529         return PUI_ERROR_INTERNAL;
530 }
531
532 pui_error
533 pui_ani_control(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat)
534 {
535         return _pui_ani_control_with_force(ani_h, cmd, repeat, 0);
536 }
537
538 static Eina_Bool
539 _cb_visibility_change(void *data, int type EINA_UNUSED, void *event)
540 {
541         pui_ani_h ani_h =  (pui_ani_h)data;
542         pui_ani_t *ani = ani_h->ani;
543         pui_h ph = ani_h->pui_handle;
544
545         Ecore_Wl2_Event_Window_Visibility_Change *ev;
546         PUI_Event_Animation_Status *e = NULL;
547
548         if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
549         {
550                 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
551                 return ECORE_CALLBACK_PASS_ON;
552         }
553
554         if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
555         {
556                 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
557                 return ECORE_CALLBACK_PASS_ON;
558         }
559
560         if (!PUI_MAGIC_CHECK(ph, PUI_MAGIC_PUI_H))
561         {
562                 PUI_MAGIC_FAIL(ph, PUI_MAGIC_PUI_H, __FUNCTION__);
563                 return ECORE_CALLBACK_PASS_ON;
564         }
565
566         ev = event;
567
568         /* check if this is needed */
569         ph->visibility = !(ev->fully_obscured);
570
571         if (ev->fully_obscured)
572         {
573                 if (ani->status == PUI_ANI_STATUS_RUNNING)
574                 {
575                         pui_info("animation(%s) will be stopped as it lost its priority !\n", ani->id);
576
577                         _pui_ani_control_with_force(ani_h, PUI_ANI_CMD_STOP, 0, 1);
578                 }
579         }
580         else
581         {
582                 if (ani->status == PUI_ANI_STATUS_PAUSED)
583                 {
584                         e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
585
586                         if (!e)
587                         {
588                                 pui_err("Failed to allocate memory for PUI Event !\n");
589                                 return ECORE_CALLBACK_PASS_ON;
590                         }
591
592                         e->ani_h = ani_h;
593                         e->win = ev->win;
594                         e->status = ani->status;
595
596                         if(ani->status == PUI_ANI_STATUS_PAUSED)
597                         {
598                                 pui_info("[Event added][ani id:%s] PUI_EVENT_ANI_READY_TO_RESUME event has been added.\n", ani_h->id);
599                                 ecore_event_add(PUI_EVENT_ANI_READY_TO_RESUME, e, NULL, ani_h);
600                         }
601                 }
602         }
603
604         return ECORE_CALLBACK_PASS_ON;
605 }
606
607 static void
608 _pui_ani_event_handlers_init(pui_ani_h ani_h)
609 {
610         Ecore_Event_Handler *h = NULL;
611
612         if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
613         {
614                 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
615                 return;
616         }
617
618         if (!ani_h->ecore_event_hdls)
619                 ani_h->ecore_event_hdls = eina_array_new(1);
620
621         h = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, _cb_visibility_change, ani_h);
622         eina_array_push(ani_h->ecore_event_hdls, h);
623
624 }
625
626 static void
627 _pui_ani_event_handlers_shutdown(pui_ani_h ani_h)
628 {
629         if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
630         {
631                 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
632                 return;
633         }
634
635         if (ani_h->ecore_event_hdls)
636         {
637                 while (eina_array_count(ani_h->ecore_event_hdls))
638                         ecore_event_handler_del(eina_array_pop(ani_h->ecore_event_hdls));
639
640                 eina_array_free(ani_h->ecore_event_hdls);
641                 ani_h->ecore_event_hdls = NULL;
642         }
643 }
644
645 pui_ani_h
646 pui_ani_create(pui_h handle, pui_id id)
647 {
648         pui_ani_h ani_h = NULL;
649         pui_ani_t *ani = NULL;
650         pui_backend_ani_data *ani_data = NULL;
651
652         if (!PUI_MAGIC_CHECK(handle, PUI_MAGIC_PUI_H))
653         {
654                 PUI_MAGIC_FAIL(handle, PUI_MAGIC_PUI_H, __FUNCTION__);
655                 return NULL;
656         }
657
658         if (!handle->backend_module_data)
659         {
660                 pui_err("Invalid backend module data !\n");
661                 return NULL;
662         }
663
664         ani_data = handle->backend_module_data->ani_create(id);
665
666         if (!ani_data)
667         {
668                 pui_err("Invalid ani data from backend module data !\n");
669                 return NULL;
670         }
671
672         ani_h = (pui_ani_h)calloc(1, sizeof(pui_ani));
673
674         if (!ani_h)
675         {
676                 pui_err("Failed to allocate memory for pui ani handle !\n");
677                 goto err;
678         }
679
680         ani_h->id = strdup(id);
681         ani_h->pui_handle = handle;
682         ani_h->ecore_event_hdls = NULL;
683
684         PUI_MAGIC_SET(ani_h, PUI_MAGIC_ANI_H);
685
686         _pui_ani_event_handlers_init(ani_h);
687
688         ani = (pui_ani_t *)calloc(1, sizeof(pui_ani_t));
689
690         if (!ani)
691         {
692                 pui_err("Failed to allocate memory for pui ani mgr !\n");
693                 goto err;
694         }
695
696         ani->ani_h = ani_h;
697         ani->id = id;
698         ani->cmd = PUI_ANI_CMD_NONE;
699         ani->repeat = 0;
700         ani->status = PUI_ANI_STATUS_INITIAL;
701         ani->ani_data = ani_data;
702
703         ani_h->ani = ani;
704
705         handle->ani_handles = eina_list_append(handle->ani_handles, ani_h);
706
707         PUI_MAGIC_SET(ani, PUI_MAGIC_ANI_T);
708
709         return ani_h;
710
711 err:
712         if (ani_data)
713         {
714                 handle->backend_module_data->ani_destroy(ani_data);
715         }
716
717         if (ani_h)
718         {
719                 PUI_MAGIC_SET(ani_h, PUI_MAGIC_NONE);
720                 free(ani_h);
721         }
722
723         return NULL;
724 }
725
726 void
727 pui_ani_destroy(pui_ani_h ani_h)
728 {
729         pui_h handle = NULL;
730         pui_ani_t *ani = NULL;
731         pui_backend_module_data *backend_module_data = NULL;
732
733         if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
734         {
735                 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
736                 return;
737         }
738
739         handle = ani_h->pui_handle;
740         ani = ani_h->ani;
741
742         if (!PUI_MAGIC_CHECK(handle, PUI_MAGIC_PUI_H))
743         {
744                 PUI_MAGIC_FAIL(handle, PUI_MAGIC_PUI_H, __FUNCTION__);
745                 return;
746         }
747
748         if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
749         {
750                 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
751                 return;
752         }
753
754         /* stop the animation being played already if any */
755         if (ani->status == PUI_ANI_STATUS_STARTED || ani->status == PUI_ANI_STATUS_RUNNING)
756                 pui_ani_control(ani_h, PUI_ANI_CMD_STOP, 0);
757
758         backend_module_data = handle->backend_module_data;
759         backend_module_data->ani_destroy(ani->ani_data);
760         ani->ani_data = NULL;
761
762         if (ani->frame_cb_timer)
763         {
764                 ecore_timer_del(ani->frame_cb_timer);
765                 ani->frame_cb_timer = NULL;
766         }
767
768         PUI_MAGIC_SET(ani_h->ani, PUI_MAGIC_NONE);
769         free(ani_h->ani);
770
771         _pui_ani_event_handlers_shutdown(ani_h);
772
773         if (ani_h->frame_done_cb)
774         {
775                 ecore_wl2_window_frame_callback_del(ani_h->frame_done_cb);
776                 ani_h->frame_done_cb = NULL;
777         }
778
779         handle->ani_handles = eina_list_remove(handle->ani_handles, ani_h);
780
781         PUI_MAGIC_SET(ani_h, PUI_MAGIC_NONE);
782
783         free(ani_h->id);
784         free(ani_h);
785 }
786