2 * Copyright © 2019 Samsung Electronics co., Ltd. All Rights Reserved.
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:
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.
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
26 #include "PUI_internal.h"
27 #include "PUI_backend.h"
32 _pui_ani_error_to_int_error(pui_error e)
39 ei = PUI_INT_ERROR_NONE;
42 case PUI_ERROR_INVALID_HANDLE:
43 ei = PUI_INT_ERROR_INVALID_HANDLE;
46 case PUI_ERROR_INVALID_SURFACE:
47 ei = PUI_INT_ERROR_INVALID_SURFACE;
50 case PUI_ERROR_INVALID_BUFFER:
51 ei = PUI_INT_ERROR_INVALID_BUFFER;
55 ei = PUI_INT_ERROR_UNKNOWN;
63 _pui_ani_cb_frame_done(Ecore_Wl2_Window *win, uint32_t timestamp EINA_UNUSED, void *data)
65 pui_h handle = (pui_h) data;
67 pui_info("Frame done ! (window=0x%x)\n", ecore_wl2_window_id_get(win));
69 /* TODO : make use of handle */
75 pui_ani_control_buffer *
76 pui_ani_get_last_buffer(pui_ani_h ani_h)
79 pui_ani_control_buffer *buffer = NULL;
81 if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
83 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
87 handle = ani_h->pui_handle;
88 buffer = pui_display_get_last_buffer(handle);
93 pui_ani_control_buffer *
94 pui_ani_get_buffer(pui_ani_h ani_h)
97 pui_ani_control_buffer *buffer = NULL;
99 if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
101 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
105 handle = ani_h->pui_handle;
106 buffer = pui_display_get_buffer(handle);
112 pui_ani_set_buffer(pui_ani_h ani_h, pui_ani_control_buffer *buffer)
114 pui_error e = PUI_ERROR_NONE;
117 if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
119 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
120 return PUI_ERROR_INVALID_HANDLE;
123 handle = ani_h->pui_handle;
125 if (!PUI_MAGIC_CHECK(handle, PUI_MAGIC_PUI_H))
127 PUI_MAGIC_FAIL(handle, PUI_MAGIC_PUI_H, __FUNCTION__);
128 return PUI_ERROR_INVALID_HANDLE;
131 e = pui_display_set_buffer(handle, buffer);
133 return _pui_ani_error_to_int_error(e);
137 pui_ani_update(pui_ani_h ani_h)
139 pui_error e = PUI_ERROR_NONE;
144 pui_err("Invalid ani handle !\n");
145 return PUI_INT_ERROR_INVALID_HANDLE;
148 handle = ani_h->pui_handle;
149 e = pui_display_update(handle);
151 return _pui_ani_error_to_int_error(e);
155 _pui_ani_frame_cb(void *data)
158 Ecore_Timer *timer = NULL;
160 pui_ani_t *ani = (pui_ani_t *)data;
162 if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
164 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
165 return ECORE_CALLBACK_CANCEL;
168 if (!ani->backend_frame_cb)
170 pui_err("Invalid backend frame_cb !\n");
171 return ECORE_CALLBACK_CANCEL;
174 if (!ani->frame_cb_timer)
176 pui_err("Invalid frame_cb timer !\n");
177 return ECORE_CALLBACK_CANCEL;
182 ret = (Eina_Bool)ani->backend_frame_cb(ani, ++ani->serial);
186 pui_err("Failed on backend's frame_cb !Frame_cb will be removed forcefuly !\n");
188 pui_ani_remove_frame_cb(ani);
193 if (ret && PUI_ANI_STATUS_STARTED == ani->status)
194 pui_ani_status_update(ani, PUI_ANI_STATUS_RUNNING);
196 ecore_timer_del(ani->frame_cb_timer);
197 ani->frame_cb_timer = NULL;
199 timer = ecore_timer_add(ani->frame_interval, _pui_ani_frame_cb, ani);
203 pui_err("Failed to add ecore timer !\n");
207 ani->frame_cb_timer = timer;
213 pui_ani_add_frame_cb(pui_ani_t *ani, pui_bool (*frame_cb)(void *data, int serial), double frame_interval)
215 Ecore_Timer *timer = NULL;
217 if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
219 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
223 if (frame_interval <= 0.0f)
225 pui_err("Invalid frame interval (%.2f) ! frame interval must be larger than 0.\n", frame_interval);
229 ani->frame_cb = _pui_ani_frame_cb;
230 ani->backend_frame_cb = frame_cb;
231 ani->frame_interval = frame_interval;
232 ani->frame_cb_data = ani;
235 timer = ecore_timer_add(frame_interval, _pui_ani_frame_cb, ani);
239 pui_err("Failed to add ecore timer !\n");
243 ani->frame_cb_timer = timer;
245 pui_info("[Frame callback added][ani id=%s] frame_interval=%.2f\n", ani->id, frame_interval);
247 /* call frame_cb for starting the first frame */
248 _pui_ani_frame_cb(ani);
254 pui_ani_remove_frame_cb(pui_ani_t *ani)
256 if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
258 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
262 if (ani->frame_cb_timer)
264 ecore_timer_del(ani->frame_cb_timer);
265 ani->frame_cb_timer = NULL;
268 ani->frame_cb = NULL;
269 ani->backend_frame_cb = NULL;
270 ani->frame_interval = 0;
271 ani->frame_cb_data = NULL;
273 pui_info("[Frame callback removed][ani id=%s]\n", ani->id);
277 pui_ani_get_id(pui_ani_h ani_h)
279 if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
281 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
285 if (!PUI_MAGIC_CHECK(ani_h->ani, PUI_MAGIC_ANI_T))
287 PUI_MAGIC_FAIL(ani_h->ani, PUI_MAGIC_ANI_T, __FUNCTION__);
291 return ani_h->ani->id;
295 pui_ani_get_cmd(pui_ani_h ani_h)
297 if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
299 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
300 return PUI_ANI_CMD_NONE;
303 if (!PUI_MAGIC_CHECK(ani_h->ani, PUI_MAGIC_ANI_T))
305 PUI_MAGIC_FAIL(ani_h->ani, PUI_MAGIC_ANI_T, __FUNCTION__);
306 return PUI_ANI_CMD_NONE;
309 return ani_h->ani->cmd;
313 pui_ani_get_repeat(pui_ani_h ani_h)
315 if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
317 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
321 if (!PUI_MAGIC_CHECK(ani_h->ani, PUI_MAGIC_ANI_T))
323 PUI_MAGIC_FAIL(ani_h->ani, PUI_MAGIC_ANI_T, __FUNCTION__);
327 return ani_h->ani->repeat;
330 pui_backend_ani_data *
331 pui_ani_get_ani_data(pui_ani_t *ani)
333 if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
335 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
339 return ani->ani_data;
343 pui_ani_status_update(pui_ani_t *ani, pui_ani_status status)
347 PUI_Event_Animation_Status *e = NULL;
349 if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
351 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
355 if (ani->status == status)
360 ani->status = status;
364 case PUI_ANI_STATUS_STARTED:
365 ev_type = PUI_EVENT_ANI_STARTED;
366 pui_info("[Status update][ani id:%s] PUI_EVENT_ANI_STARTED event has been added.\n", ani->id);
369 case PUI_ANI_STATUS_RUNNING:
370 pui_info("[Status update][ani id:%s] PUI_ANI_STATUS_RUNNING !\n", ani->id);
373 case PUI_ANI_STATUS_PAUSED:
374 ev_type = PUI_EVENT_ANI_PAUSED;
375 pui_info("[Status update][ani id:%s] PUI_EVENT_ANI_PAUSED event has been added.\n", ani->id);
378 case PUI_ANI_STATUS_STOPPED:
379 ev_type = PUI_EVENT_ANI_STOPPED;
380 pui_info("[Status update][ani id:%s] PUI_EVENT_ANI_STOPPED event has been added.\n", ani->id);
384 pui_err("Unknown status !(ani status=%d, id=%s) !\n", status, ani->id);
390 e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
394 pui_err("Failed to allocate memory for PUI Event !\n");
399 e->win = ecore_wl2_window_id_get(ani_h->pui_handle->win);
402 ecore_event_add(ev_type, e, NULL, ani_h);
407 pui_ani_status_get(pui_ani_t *ani)
409 pui_ani_status status = PUI_ANI_STATUS_UNKNOWN;
411 if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
413 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
421 _pui_ani_control_with_force(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat, pui_bool force)
423 pui_int_error ei = PUI_INT_ERROR_NONE;
424 pui_ani_t *ani = NULL;
426 pui_backend_ani_func *ani_func = NULL;
428 if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
430 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
431 return PUI_ERROR_INVALID_ANI_HANDLE;
434 if (cmd < PUI_ANI_CMD_START || cmd >= PUI_ANI_CMD_LAST)
436 pui_err("Invalid cmd ! (cmd=%d)\n", cmd);
437 return PUI_ERROR_INVALID_ANI_CMD;
442 pui_err("Invalid repeat count ! (repeat=%d)\n", repeat);
443 return PUI_ERROR_INVALID_ANI_REPEAT;
446 handle = ani_h->pui_handle;
449 if (!PUI_MAGIC_CHECK(handle, PUI_MAGIC_PUI_H))
451 PUI_MAGIC_FAIL(handle, PUI_MAGIC_PUI_H, __FUNCTION__);
452 return PUI_ERROR_INTERNAL;
455 if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
457 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
458 return PUI_ERROR_INTERNAL;
463 pui_err("Invalid ani_data !\n");
464 return PUI_ERROR_INTERNAL;
467 ani_func = ani->ani_data->ani_func;
470 ani->repeat = repeat;
472 if (cmd == PUI_ANI_CMD_START)
474 if (handle->manual_render)
476 pui_err("Manual render has been set ! Unable to start animation.\n");
477 return PUI_ERROR_MANUAL_RENDER_ENABLED;
480 if (handle->current_ani_h && handle->current_ani_h != ani_h)
482 pui_ani_t *current_ani = handle->current_ani_h->ani;
484 if (current_ani->status >= PUI_ANI_STATUS_STARTED &&
485 current_ani->status <= PUI_ANI_STATUS_RUNNING)
487 pui_info("current_ani id=%s, status=%d\n", current_ani->id, current_ani->status);
489 ei = _pui_ani_control_with_force(handle->current_ani_h, PUI_ANI_CMD_STOP, 0, force);
491 if (ei != PUI_INT_ERROR_NONE)
492 pui_info("Failed to stop running previous animation ! (id:%s)\n", current_ani->id);
495 handle->current_ani_h = NULL;
499 ei = ani_func->ani_start(ani, repeat);
501 if (ei != PUI_INT_ERROR_NONE)
503 pui_err("Error on starting animation ! (id:%s, repeat:%d, status=%d))\n", ani->id, repeat, ani->status);
505 if (ani->status != PUI_ANI_STATUS_RUNNING)
506 _pui_ani_control_with_force(ani_h, PUI_ANI_CMD_STOP, 0, 0);
508 return PUI_ERROR_INTERNAL;
511 handle->current_ani_h = ani_h;
513 else//cmd == PUI_ANI_CMD_STOP
515 ei = ani_func->ani_stop(ani, force);
517 if (ani->frame_cb_timer)
518 pui_ani_remove_frame_cb(ani);
520 if (ei != PUI_INT_ERROR_NONE)
522 pui_err("Failied on stopping animation ! (id:%s)\n", ani->id);
524 if (ani->status != PUI_ANI_STATUS_STOPPED)
525 pui_ani_status_update(ani, PUI_ANI_STATUS_STOPPED);
527 return PUI_ERROR_INTERNAL;
530 return PUI_ERROR_NONE;
533 ani_h->frame_done_cb = ecore_wl2_window_frame_callback_add(handle->win, _pui_ani_cb_frame_done, handle);
535 if (!ani_h->frame_done_cb)
537 pui_err("Failed to add frame callback !");
541 return PUI_ERROR_NONE;
544 return PUI_ERROR_INTERNAL;
548 pui_ani_control(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat)
550 return _pui_ani_control_with_force(ani_h, cmd, repeat, 0);
554 _cb_visibility_change(void *data, int type EINA_UNUSED, void *event)
556 pui_ani_h ani_h = (pui_ani_h)data;
557 pui_ani_t *ani = ani_h->ani;
558 pui_h ph = ani_h->pui_handle;
560 Ecore_Wl2_Event_Window_Visibility_Change *ev;
561 PUI_Event_Animation_Status *e = NULL;
563 if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
565 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
566 return ECORE_CALLBACK_PASS_ON;
569 if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
571 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
572 return ECORE_CALLBACK_PASS_ON;
575 if (!PUI_MAGIC_CHECK(ph, PUI_MAGIC_PUI_H))
577 PUI_MAGIC_FAIL(ph, PUI_MAGIC_PUI_H, __FUNCTION__);
578 return ECORE_CALLBACK_PASS_ON;
583 /* check if this is needed */
584 ph->visibility = !(ev->fully_obscured);
586 if (ev->fully_obscured)
588 if (ani->status == PUI_ANI_STATUS_RUNNING)
590 pui_info("animation(%s) will be stopped as it lost its priority !\n", ani->id);
592 _pui_ani_control_with_force(ani_h, PUI_ANI_CMD_STOP, 0, 1);
597 if (ani->status == PUI_ANI_STATUS_PAUSED)
599 e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
603 pui_err("Failed to allocate memory for PUI Event !\n");
604 return ECORE_CALLBACK_PASS_ON;
609 e->status = ani->status;
611 if(ani->status == PUI_ANI_STATUS_PAUSED)
613 pui_info("[Event added][ani id:%s] PUI_EVENT_ANI_READY_TO_RESUME event has been added.\n", ani_h->id);
614 ecore_event_add(PUI_EVENT_ANI_READY_TO_RESUME, e, NULL, ani_h);
619 return ECORE_CALLBACK_PASS_ON;
623 _pui_ani_event_handlers_init(pui_ani_h ani_h)
625 Ecore_Event_Handler *h = NULL;
627 if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
629 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
633 if (!ani_h->ecore_event_hdls)
634 ani_h->ecore_event_hdls = eina_array_new(1);
636 h = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, _cb_visibility_change, ani_h);
637 eina_array_push(ani_h->ecore_event_hdls, h);
642 _pui_ani_event_handlers_shutdown(pui_ani_h ani_h)
644 if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
646 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
650 if (ani_h->ecore_event_hdls)
652 while (eina_array_count(ani_h->ecore_event_hdls))
653 ecore_event_handler_del(eina_array_pop(ani_h->ecore_event_hdls));
655 eina_array_free(ani_h->ecore_event_hdls);
656 ani_h->ecore_event_hdls = NULL;
661 pui_ani_create(pui_h handle, pui_id id)
663 pui_ani_h ani_h = NULL;
664 pui_ani_t *ani = NULL;
665 pui_backend_ani_data *ani_data = NULL;
667 if (!PUI_MAGIC_CHECK(handle, PUI_MAGIC_PUI_H))
669 PUI_MAGIC_FAIL(handle, PUI_MAGIC_PUI_H, __FUNCTION__);
673 if (!handle->backend_module_data)
675 pui_err("Invalid backend module data !\n");
679 ani_data = handle->backend_module_data->ani_create(id);
683 pui_err("Invalid ani data from backend module data !\n");
687 ani_h = (pui_ani_h)calloc(1, sizeof(pui_ani));
691 pui_err("Failed to allocate memory for pui ani handle !\n");
695 ani_h->id = strdup(id);
696 ani_h->pui_handle = handle;
697 ani_h->ecore_event_hdls = NULL;
699 PUI_MAGIC_SET(ani_h, PUI_MAGIC_ANI_H);
701 _pui_ani_event_handlers_init(ani_h);
703 ani = (pui_ani_t *)calloc(1, sizeof(pui_ani_t));
707 pui_err("Failed to allocate memory for pui ani mgr !\n");
713 ani->cmd = PUI_ANI_CMD_NONE;
715 ani->status = PUI_ANI_STATUS_INITIAL;
716 ani->ani_data = ani_data;
720 handle->ani_handles = eina_list_append(handle->ani_handles, ani_h);
722 PUI_MAGIC_SET(ani, PUI_MAGIC_ANI_T);
729 handle->backend_module_data->ani_destroy(ani_data);
734 PUI_MAGIC_SET(ani_h, PUI_MAGIC_NONE);
742 pui_ani_destroy(pui_ani_h ani_h)
745 pui_ani_t *ani = NULL;
746 pui_backend_module_data *backend_module_data = NULL;
748 if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H))
750 PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__);
754 handle = ani_h->pui_handle;
757 if (!PUI_MAGIC_CHECK(handle, PUI_MAGIC_PUI_H))
759 PUI_MAGIC_FAIL(handle, PUI_MAGIC_PUI_H, __FUNCTION__);
763 if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T))
765 PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__);
769 /* stop the animation being played already if any */
770 if (ani->status == PUI_ANI_STATUS_STARTED || ani->status == PUI_ANI_STATUS_RUNNING)
771 pui_ani_control(ani_h, PUI_ANI_CMD_STOP, 0);
773 backend_module_data = handle->backend_module_data;
774 backend_module_data->ani_destroy(ani->ani_data);
775 ani->ani_data = NULL;
777 if (ani->frame_cb_timer)
779 ecore_timer_del(ani->frame_cb_timer);
780 ani->frame_cb_timer = NULL;
783 PUI_MAGIC_SET(ani_h->ani, PUI_MAGIC_NONE);
786 _pui_ani_event_handlers_shutdown(ani_h);
788 if (ani_h->frame_done_cb)
790 ecore_wl2_window_frame_callback_del(ani_h->frame_done_cb);
791 ani_h->frame_done_cb = NULL;
794 handle->ani_handles = eina_list_remove(handle->ani_handles, ani_h);
796 PUI_MAGIC_SET(ani_h, PUI_MAGIC_NONE);