PUI & default-backend: add force argument to the control function of animation
[platform/core/uifw/libpui.git] / src / PUI_ani.c
index 808adaa..9ef7c0f 100644 (file)
 static int KEY_WL_BUFFER = 0xabcdbeaf;
 static int KEY_CLIENT = 0xdcbabeaf;
 
-static Eina_Bool
-_cb_window_show(void *data, int type EINA_UNUSED, void *event)
-{
-       pui_ani_h handle =  (pui_ani_h)data;
-       Ecore_Wl2_Event_Window_Show *ev = (Ecore_Wl2_Event_Window_Show *)event;
-
-       pui_info("...\n");
-
-       /* TODO */
-       (void) handle;
-       (void) ev;
-
-       return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_cb_focus_in(void *data, int type EINA_UNUSED, void *event)
-{
-       pui_ani_h handle =  (pui_ani_h)data;
-       Ecore_Wl2_Event_Focus_In *ev = (Ecore_Wl2_Event_Focus_In *)event;
-
-       pui_info("...\n");
-
-       /* TODO */
-       (void) handle;
-       (void) ev;
-
-       return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_cb_focus_out(void *data, int type EINA_UNUSED, void *event)
-{
-       pui_ani_h handle =  (pui_ani_h)data;
-       Ecore_Wl2_Event_Focus_Out *ev = (Ecore_Wl2_Event_Focus_Out *)event;
-
-       pui_info("...\n");
-
-       /* TODO */
-       (void) handle;
-       (void) ev;
-
-       return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_cb_visibility_change(void *data, int type EINA_UNUSED, void *event)
-{
-       pui_ani_h ani_h =  (pui_ani_h)data;
-       pui_ani_t *ani = ani_h->ani;
-       pui_h ph = ani_h->pui_handle;
-
-       Ecore_Wl2_Event_Window_Visibility_Change *ev;
-       PUI_Event_Animation_Status *e = NULL;
-
-       ev = event;
-
-       pui_info("Visibility change (window=0x%x, fully_obscured=%d)\n", ev->win, ev->fully_obscured);
-
-       /* check if this is needed */
-       ph->visibility = !(ev->fully_obscured);
-
-       if (ev->fully_obscured)
-       {
-               if (ani->status == PUI_ANI_STATUS_RUNNING)
-               {
-                       ani->status = PUI_ANI_STATUS_STOPPED;
-
-                       e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
-
-                       if (!e)
-                       {
-                               pui_err("Failed to allocate memory for PUI Event !\n");
-                               return ECORE_CALLBACK_PASS_ON;
-                       }
-                       
-                       e->win = ev->win;
-                       e->status = PUI_ANI_STATUS_FORCE_STOPPED;
-                       
-                       ecore_event_add(PUI_EVENT_ANI_STOPPED, e, NULL, ani_h);
-               }
-       }
-       else
-       {
-               e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
-               
-               if (!e)
-               {
-                       pui_err("Failed to allocate memory for PUI Event !\n");
-                       return ECORE_CALLBACK_PASS_ON;
-               }
-               
-               e->win = ev->win;
-               e->status = ani->status;
-               
-               if (ani->status == PUI_ANI_STATUS_STOPPED)
-                       ecore_event_add(PUI_EVENT_ANI_READY_TO_START, e, NULL, ani_h);
-               else if(ani->status == PUI_ANI_STATUS_PAUSED)
-                       ecore_event_add(PUI_EVENT_ANI_READY_TO_RESUME, e, NULL, ani_h);
-       }
-
-       return ECORE_CALLBACK_PASS_ON;
-}
-
 static void
 _pui_ani_cb_frame_done(Ecore_Wl2_Window *win, uint32_t timestamp EINA_UNUSED, void *data)
 {
        pui_h handle = (pui_h) data;
 
-       pui_info("Frame done ! (window=%p)\n", win);
+       pui_info("Frame done ! (window=0x%x)\n", ecore_wl2_window_id_get(win));
 
-       // TODO
+       /* TODO : make use of handle */
        (void) handle;
 
        return;
@@ -333,53 +229,6 @@ pui_ani_update(pui_ani_h ani_h)
        return PUI_INT_ERROR_NONE;
 }
 
-static void
-_pui_ani_event_handlers_init(pui_ani_h ani_h)
-{
-       Ecore_Event_Handler *h = NULL;
-
-       if (!ani_h)
-       {
-               pui_err("Invalid handle !\n");
-               return;
-       }
-
-       if (!ani_h->ecore_event_hdls)
-               ani_h->ecore_event_hdls = eina_array_new(5);
-
-       h = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_SHOW, _cb_window_show, ani_h);
-       eina_array_push(ani_h->ecore_event_hdls, h);
-
-       h = ecore_event_handler_add(ECORE_WL2_EVENT_FOCUS_IN, _cb_focus_in, ani_h);
-       eina_array_push(ani_h->ecore_event_hdls, h);
-
-       h = ecore_event_handler_add(ECORE_WL2_EVENT_FOCUS_OUT, _cb_focus_out, ani_h);
-       eina_array_push(ani_h->ecore_event_hdls, h);
-
-       h = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, _cb_visibility_change, ani_h);
-       eina_array_push(ani_h->ecore_event_hdls, h);
-
-}
-
-static void
-_pui_ani_event_handlers_shutdown(pui_ani_h ani_h)
-{
-       if (!ani_h)
-       {
-               pui_err("Invalid handle !\n");
-               return;
-       }
-
-       if (ani_h->ecore_event_hdls)
-       {
-               while (eina_array_count(ani_h->ecore_event_hdls))
-                       ecore_event_handler_del(eina_array_pop(ani_h->ecore_event_hdls));
-
-               eina_array_free(ani_h->ecore_event_hdls);
-               ani_h->ecore_event_hdls = NULL;
-       }
-}
-
 static Eina_Bool
 _pui_ani_frame_cb(void *data)
 {
@@ -405,13 +254,23 @@ _pui_ani_frame_cb(void *data)
                return ECORE_CALLBACK_CANCEL;
        }
 
-       pui_info("frame_cb !\n");
+       pui_info("...\n");
 
        ret = (Eina_Bool)ani->backend_frame_cb(ani, ++ani->serial);
 
-       pui_ani_status_update(ani, PUI_ANI_STATUS_RUNNING);
+       if (!ret)
+       {
+               pui_err("Failed on backend's frame_cb !Frame_cb will be removed forcefuly !\n");
+
+               pui_ani_remove_frame_cb(ani);
 
-       return ret;
+               return EINA_FALSE;
+       }
+
+       if (ret && PUI_ANI_STATUS_STARTED == ani->status)
+               pui_ani_status_update(ani, PUI_ANI_STATUS_RUNNING);
+
+       return EINA_TRUE;
 }
 
 pui_bool
@@ -425,6 +284,12 @@ pui_ani_add_frame_cb(pui_ani_t *ani, pui_bool (*frame_cb)(void *data, int serial
                return 0;
        }
 
+       if (frame_interval <= 0.0f)
+       {
+               pui_err("Invalid frame interval (%.2f) ! frame interval must be larger than 0.\n", frame_interval);
+               return 0;
+       }
+
        ani->frame_cb = _pui_ani_frame_cb;
        ani->backend_frame_cb = frame_cb;
        ani->frame_interval = frame_interval;
@@ -441,6 +306,8 @@ pui_ani_add_frame_cb(pui_ani_t *ani, pui_bool (*frame_cb)(void *data, int serial
 
        ani->frame_cb_timer = timer;
 
+       pui_info("[Frame callback added][ani id=%s] frame_interval=%.2f\n", ani->id, frame_interval);
+
        /* call frame_cb for starting the first frame */
        _pui_ani_frame_cb(ani);
 
@@ -451,7 +318,10 @@ void
 pui_ani_remove_frame_cb(pui_ani_t *ani)
 {
        if (!ani)
+       {
+               pui_err("Invalid put ani !\n");
                return;
+       }
 
        if (ani->frame_cb_timer)
        {
@@ -463,6 +333,8 @@ pui_ani_remove_frame_cb(pui_ani_t *ani)
        ani->backend_frame_cb = NULL;
        ani->frame_interval = 0;
        ani->frame_cb_data = NULL;
+
+       pui_info("[Frame callback removed][ani id=%s]\n", ani->id);
 }
 
 pui_id
@@ -504,9 +376,64 @@ pui_ani_get_ani_data(pui_ani_t *ani)
 void
 pui_ani_status_update(pui_ani_t *ani, pui_ani_status status)
 {
-       //TODO : add PUI EVENT
+       int ev_type = -1;
+       pui_ani_h ani_h;
+       PUI_Event_Animation_Status *e = NULL;
+
+       if (!ani)
+       {
+               pui_err("Invalid pui ani !\n");
+               return;
+       }
+
+       if (ani->status == status)
+               return;
+
+       ani_h = ani->ani_h;
+
+       e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
+
+       if (!e)
+       {
+               pui_err("Failed to allocate memory for PUI Event !\n");
+               return;
+       }
 
        ani->status = status;
+       e->ani_h = ani_h;
+       e->win = ecore_wl2_window_id_get(ani_h->pui_handle->win);
+       e->status = status;
+
+       switch (status)
+       {
+               case PUI_ANI_STATUS_STARTED:
+                       ev_type = PUI_EVENT_ANI_STARTED;
+                       pui_info("[Status update][ani id:%s] PUI_EVENT_ANI_STARTED event has been added.\n", ani->id);
+                       break;
+
+               case PUI_ANI_STATUS_RUNNING:
+                       pui_info("[Status update][ani id:%s] PUI_ANI_STATUS_RUNNING !\n", ani->id);
+                       break;
+
+               case PUI_ANI_STATUS_PAUSED:
+                       ev_type = PUI_EVENT_ANI_PAUSED;
+                       pui_info("[Status update][ani id:%s] PUI_EVENT_ANI_PAUSED event has been added.\n", ani->id);
+                       break;
+
+               case PUI_ANI_STATUS_STOPPED:
+                       ev_type = PUI_EVENT_ANI_STOPPED;
+                       pui_info("[Status update][ani id:%s] PUI_EVENT_ANI_STOPPED event has been added.\n", ani->id);
+                       break;
+
+               default:
+                       pui_err("Unknown status !(ani status=%d, id=%s) !\n", status, ani->id);
+                       return;
+       }
+
+       if (ev_type > 0)
+       {
+               ecore_event_add(ev_type, e, NULL, ani_h);
+       }
 }
 
 pui_ani_status
@@ -523,9 +450,10 @@ pui_ani_status_get(pui_ani_t *ani)
        return ani->status;
 }
 
-pui_error
-pui_ani_control(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat)
+static pui_error
+_pui_ani_control_with_force(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat, pui_bool force)
 {
+       pui_int_error ei = PUI_INT_ERROR_NONE;
        pui_ani_t *ani = NULL;
        pui_h handle = NULL;
        pui_backend_ani_func *ani_func = NULL;
@@ -535,7 +463,7 @@ pui_ani_control(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat)
 
        if (cmd < PUI_ANI_CMD_START || cmd >= PUI_ANI_CMD_LAST)
        {
-               pui_err("Invalid cmd ! (repeat=%d)\n", repeat);
+               pui_err("Invalid cmd ! (cmd=%d)\n", cmd);
                return PUI_ERROR_INVALID_ANI_CMD;
        }
 
@@ -545,9 +473,6 @@ pui_ani_control(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat)
                return PUI_ERROR_INVALID_ANI_REPEAT;
        }
 
-       //TODO : check if there is any animation being played already
-       //NOTE : the id of the animation being played can be different from ani_h->id
-
        handle = ani_h->pui_handle;
        ani = ani_h->ani;
 
@@ -564,11 +489,56 @@ pui_ani_control(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat)
 
        if (cmd == PUI_ANI_CMD_START)
        {
-               ani_func->ani_start(ani, repeat);
+               if (handle->current_ani_h && handle->current_ani_h != ani_h)
+               {
+                       pui_ani_t *current_ani = handle->current_ani_h->ani;
+
+                       if (current_ani->status >= PUI_ANI_STATUS_STARTED &&
+                               current_ani->status <= PUI_ANI_STATUS_RUNNING)
+                       {
+                               pui_info("current_ani id=%s, status=%d\n", current_ani->id, current_ani->status);
+
+                               ei = _pui_ani_control_with_force(handle->current_ani_h, PUI_ANI_CMD_STOP, 0, force);
+
+                               if (ei != PUI_INT_ERROR_NONE)
+                                       pui_info("Failed to stop running previous animation ! (id:%s)\n", current_ani->id);
+
+                               current_ani = NULL;
+                               handle->current_ani_h = NULL;
+                       }
+               }
+
+               ei = ani_func->ani_start(ani, repeat);
+
+               if (ei != PUI_INT_ERROR_NONE)
+               {
+                       pui_err("Error on starting animation ! (id:%s, repeat:%d, status=%d))\n", ani->id, repeat, ani->status);
+
+                       if (ani->status != PUI_ANI_STATUS_RUNNING)
+                               _pui_ani_control_with_force(ani_h, PUI_ANI_CMD_STOP, 0, 0);
+
+                       return PUI_ERROR_INTERNAL;
+               }
+
+               handle->current_ani_h = ani_h;
        }
        else//cmd == PUI_ANI_CMD_STOP
        {
-               ani_func->ani_stop(ani);
+               ei = ani_func->ani_stop(ani, force);
+
+               if (ei != PUI_INT_ERROR_NONE)
+               {
+                       pui_err("Failied on stopping animation ! (id:%s)\n", ani->id);
+
+                       if (ani->status != PUI_ANI_STATUS_STOPPED)
+                               pui_ani_status_update(ani, PUI_ANI_STATUS_STOPPED);
+
+                       if (ani->frame_cb_timer)
+                               pui_ani_remove_frame_cb(ani);
+
+                       return PUI_ERROR_INTERNAL;
+               }
+
                return PUI_ERROR_NONE;
        }
 
@@ -580,14 +550,107 @@ pui_ani_control(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat)
                goto err;
        }
 
-       //TODO
-
        return PUI_ERROR_NONE;
 
 err:
        return PUI_ERROR_INTERNAL;
 }
 
+pui_error
+pui_ani_control(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat)
+{
+       return _pui_ani_control_with_force(ani_h, cmd, repeat, 0);
+}
+
+static Eina_Bool
+_cb_visibility_change(void *data, int type EINA_UNUSED, void *event)
+{
+       pui_ani_h ani_h =  (pui_ani_h)data;
+       pui_ani_t *ani = ani_h->ani;
+       pui_h ph = ani_h->pui_handle;
+
+       Ecore_Wl2_Event_Window_Visibility_Change *ev;
+       PUI_Event_Animation_Status *e = NULL;
+
+       ev = event;
+
+       /* check if this is needed */
+       ph->visibility = !(ev->fully_obscured);
+
+       if (ev->fully_obscured)
+       {
+               if (ani->status == PUI_ANI_STATUS_RUNNING)
+               {
+                       pui_info("animation(%s) will be stopped as it lost its priority !\n", ani->id);
+
+                       _pui_ani_control_with_force(ani_h, PUI_ANI_CMD_STOP, 0, 1);
+               }
+       }
+       else
+       {
+               if (ani->status == PUI_ANI_STATUS_PAUSED)
+               {
+                       e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
+
+                       if (!e)
+                       {
+                               pui_err("Failed to allocate memory for PUI Event !\n");
+                               return ECORE_CALLBACK_PASS_ON;
+                       }
+
+                       e->ani_h = ani_h;
+                       e->win = ev->win;
+                       e->status = ani->status;
+
+                       if(ani->status == PUI_ANI_STATUS_PAUSED)
+                       {
+                               pui_info("[Event added][ani id:%s] PUI_EVENT_ANI_READY_TO_RESUME event has been added.\n", ani_h->id);
+                               ecore_event_add(PUI_EVENT_ANI_READY_TO_RESUME, e, NULL, ani_h);
+                       }
+               }
+       }
+
+       return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_pui_ani_event_handlers_init(pui_ani_h ani_h)
+{
+       Ecore_Event_Handler *h = NULL;
+
+       if (!ani_h)
+       {
+               pui_err("Invalid handle !\n");
+               return;
+       }
+
+       if (!ani_h->ecore_event_hdls)
+               ani_h->ecore_event_hdls = eina_array_new(1);
+
+       h = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, _cb_visibility_change, ani_h);
+       eina_array_push(ani_h->ecore_event_hdls, h);
+
+}
+
+static void
+_pui_ani_event_handlers_shutdown(pui_ani_h ani_h)
+{
+       if (!ani_h)
+       {
+               pui_err("Invalid handle !\n");
+               return;
+       }
+
+       if (ani_h->ecore_event_hdls)
+       {
+               while (eina_array_count(ani_h->ecore_event_hdls))
+                       ecore_event_handler_del(eina_array_pop(ani_h->ecore_event_hdls));
+
+               eina_array_free(ani_h->ecore_event_hdls);
+               ani_h->ecore_event_hdls = NULL;
+       }
+}
+
 pui_ani_h
 pui_ani_create(pui_h handle, pui_id id)
 {
@@ -670,7 +733,7 @@ pui_ani_destroy(pui_ani_h ani_h)
        ani = ani_h->ani;
 
        /* stop the animation being played already if any */
-       if (ani->status != PUI_ANI_STATUS_STOPPED)
+       if (ani->status == PUI_ANI_STATUS_STARTED || ani->status == PUI_ANI_STATUS_RUNNING)
                pui_ani_control(ani_h, PUI_ANI_CMD_STOP, 0);
 
        backend_module_data = handle->backend_module_data;