default_backend: fix some svace issues
[platform/core/uifw/libpui.git] / backends / default_backend.c
index d626c69..5d71cf2 100644 (file)
-//#include <PUI.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <PUI_backend.h>
-
-#include <json-c/json.h>
-#include <dirent.h>
-#include <errno.h>
-#include <Eina.h>
-
-#define ANI_COLLECTION_DIR "/run/pui/"
-#define MAX_STR 1024
-
-#define ERROR_CHECK(exp, action, fmt, ...) \
-       do { \
-               if (!(exp)) \
-               { \
-                       printf(fmt, ##__VA_ARGS__);     \
-                       action; \
-               } \
-       } while (0)
+/*
+ * Copyright © 2019 Samsung Electronics co., Ltd. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "default_backend.h"
+#include <limits.h>
 
 pui_backend_ani_func *ani_func = NULL;
 Eina_Hash *_animations_hash = NULL;
+pui_backend_ani_data *g_ani_data = NULL;
 
-typedef enum
-{
-       None,
-       Linear,
-       EaseInSine,
-       EaseOutSine,
-       EaseInQuart,
-       EaseOutQuart
-} pui_effect_func;
-
-typedef struct _default_ani_info default_ani_info;
-typedef struct _default_frame_info_t default_frame_info_t;
-typedef struct _default_led_info_t default_led_info_t;
-
-struct _default_ani_info
+#if 0
+static double
+_ani_backend_ease_function_get_intensity(pui_effect_func func, double interval)
 {
-       pui_id id;
-       pui_ani_status status;
-       pui_ani_control_buffer *buffer;
-       unsigned int repeat;
-
-       unsigned int key_frame_idx;
-       unsigned int num_key_frames;
-       default_frame_info_t *frames;
-       int interval;
-       pui_effect_func effect_func;
-};
+       double intensity = interval;
+       switch (func)
+       {
+               case None:
+                       break;
+               case Linear:
+                       break;
+               case EaseInSine:
+                       intensity = 1 - cos(PI / 2 * interval);
+                       break;
+               case EaseOutSine:
+                       intensity = sin(PI / 2 * interval);
+                       break;
+               case EaseInQuart:
+                       intensity = interval * interval;
+                       break;
+               case EaseOutQuart:
+                       intensity = interval * (2 - interval);
+                       break;
+               default:
+                       break;
+       }
 
-struct _default_frame_info_t
-{
-       default_led_info_t *leds;
-       int num_led;
-};
+       return intensity;
+}
 
-struct _default_led_info_t
+static unsigned int
+_ani_backend_get_value(unsigned int end_frame, unsigned int start_frame, double interval)
 {
-       unsigned int color;
-};
+       double res = 0.0;
 
-pui_backend_ani_data *g_ani_data = NULL;
+       // interval: frame ratio between key frame to key frame
+       // end_frame and start_frame is key frame
+
+       res = (end_frame - start_frame) * interval + start_frame;
+
+       return res;
+}
+#endif
 
 static pui_bool
-_frame_cb(void *data, int serial)
+_ani_backend_frame_cb(void *data, int serial)
 {
+       pui_int_error e = PUI_INT_ERROR_NONE;
        pui_ani_t *ani = (pui_ani_t *)data;
+       pui_backend_ani_data *ani_data = NULL;
+       pui_ani_control_buffer *buffer = NULL;
+       double now;
 
-       //TODO
-       (void) ani;
-       //_get_next_frame();
-       //pui_backend_ani_get_buffer();
-       //pui_backend_ani_update();
+       ani_data = pui_backend_ani_get_ani_data(ani);
+       default_ani_info *ani_info = (default_ani_info *)ani_data->ani_info;
+
+       now = ecore_time_unix_get();
+
+       pui_info("[time:%.3f] serial=%d\n", now, serial);
+
+       /* TODO : make use of ani_info */
+       (void) ani_info;
+
+       buffer = pui_backend_ani_get_buffer(ani);
+
+       if (!buffer)
+       {
+               pui_err("Failed to get buffer !\n");
+               return 0;
+       }
+
+       /* test example */
+       for(int i = 0; i<12; i++)
+       {
+               buffer->ptr[4*i] = 0;
+               buffer->ptr[4*i + 1] = (ani_info->frames[ani_info->frame_idx].leds[i].color & LED_MASK_RED) >> 16;//R
+               buffer->ptr[4*i + 2] = (ani_info->frames[ani_info->frame_idx].leds[i].color & LED_MASK_GREEN) >> 8;//G
+               buffer->ptr[4*i + 3] = ani_info->frames[ani_info->frame_idx].leds[i].color & LED_MASK_BLUE;//B
+       }
+
+       e = pui_backend_ani_set_buffer(ani, buffer);
+
+       if (e != PUI_INT_ERROR_NONE)
+       {
+               pui_err("Failed on setting buffer on animation !(e=%d)\n", e);
+               return (pui_bool)0;
+       }
+
+       e = pui_backend_ani_update(ani);
+
+       if (e != PUI_INT_ERROR_NONE)
+       {
+               pui_err("Failed on updating animation !(e=%d)\n", e);
+               return (pui_bool)0;
+       }
+
+       pui_info("... update (serial=%d)\n", serial);
 
        return (pui_bool)1;
 }
 
-pui_int_error
-get_ani_info_from_ani_collection(default_ani_info *info, pui_id id)
+default_ani_info *
+get_ani_info_from_ani_collection(pui_id id)
 {
-       pui_int_error e = PUI_INT_ERROR_NONE;
+       default_ani_info *ani_info = NULL;
 
-       //TODO
-       //ex> data->id = id;
-       //ex> data->interval = 30;
+       if (!_animations_hash)
+               return NULL;
 
-       return e;
+       pui_info("... id: %s\n", id);
+
+       ani_info = eina_hash_find(_animations_hash, id);
+
+       if (!ani_info)
+       {
+               pui_err("ani_info has NOT been found ! (id:%s)\n", id);
+               return NULL;
+       }
+
+       pui_info("ani_info has been found ! (id:%s)\n", id);
+
+       return ani_info;
 }
 
 pui_error
 _ani_start(pui_ani_t *ani, int repeat)
 {
+       pui_bool ret = 0;
        pui_int_error e = PUI_INT_ERROR_NONE;
        pui_backend_ani_data *ani_data = NULL;
 
        ani_data = pui_backend_ani_get_ani_data(ani);
-       default_ani_info *info = (default_ani_info *)ani_data->ani_info;
+       default_ani_info *ani_info = (default_ani_info *)ani_data->ani_info;
 
-       //TODO
-       (void) info;
+       pui_info("... info->id: %s, repeat : %d\n", ani_info->id, repeat);
 
        pui_backend_ani_status_update(ani, PUI_ANI_STATUS_STARTED);
-       pui_backend_ani_add_frame_cb(ani, _frame_cb, 0.1);
+       ret = pui_backend_ani_add_frame_cb(ani, _ani_backend_frame_cb, (double)ani_info->interval / 1000);
+
+       if (!ret)
+       {
+               pui_err("Failed to add frame callback !\n");
+               e = PUI_INT_ERROR_INVALID_RESOURCES;
+       }
 
        return e;
 }
 
 pui_error
-_ani_stop(pui_ani_t *ani)
+_ani_stop(pui_ani_t *ani, pui_bool force)
 {
        pui_int_error e = PUI_INT_ERROR_NONE;
        pui_backend_ani_data *ani_data = NULL;
@@ -120,8 +190,14 @@ _ani_stop(pui_ani_t *ani)
        //TODO
        (void) info;
 
+       pui_info("... info->id: %s, force=%d\n", info->id, force);
+
        pui_backend_ani_remove_frame_cb(ani);
-       pui_backend_ani_status_update(ani, PUI_ANI_STATUS_STOPPED);
+
+       if (force)
+               pui_backend_ani_status_update(ani, PUI_ANI_STATUS_PAUSED);
+       else
+               pui_backend_ani_status_update(ani, PUI_ANI_STATUS_STOPPED);
 
        return e;
 }
@@ -131,25 +207,30 @@ _read_json_file(const char *path, int *data_size)
 {
        FILE *fp = fopen(path, "rb");
        int size;
-       char *buffer;
+       char *buffer = NULL;
        ERROR_CHECK(fp, return NULL, "Failed to open file: %s\n", path);
 
        fseek(fp, 0, SEEK_END);
-       size = ftell(fp);
+       size = (long int)ftell(fp);
        fseek(fp, 0, SEEK_SET);
+       ERROR_CHECK(0 < size && size < INT_MAX, goto error, "Invalid file: %d size\n", size);
 
        buffer = (char *)calloc(sizeof(char), size + 1);
+       ERROR_CHECK(buffer, goto error, "Failed to allocate memory for buffer\n");
 
        if (fread(buffer, size, 1, fp) < 1) {
-               *data_size = 0;
-               free(buffer);
-               fclose(fp);
-               return NULL;
+               goto error;
        }
 
        *data_size = size;
        fclose(fp);
        return buffer;
+
+error:
+       *data_size = 0;
+       if (buffer) free(buffer);
+       fclose(fp);
+       return NULL;
 }
 
 static default_ani_info *
@@ -162,7 +243,7 @@ _read_json(const char *path)
        int data_size = 0, i, j;
 
        buffer = _read_json_file(path, &data_size);
-       ERROR_CHECK(buffer && data_size > 0, return EINA_FALSE, "File %s has no data\n", path);
+       ERROR_CHECK(buffer && data_size > 0, goto error, "File %s has no data\n", path);
        root_obj = json_tokener_parse(buffer);
        ERROR_CHECK(root_obj, goto error, "Failed to tokenize json object\n");
 
@@ -184,7 +265,7 @@ _read_json(const char *path)
        ani_info->num_key_frames = frame_len;
        ani_info->frames = (default_frame_info_t *)calloc(sizeof(default_frame_info_t), frame_len);
        ERROR_CHECK(ani_info->frames, goto error, "Failed to alloc for default_frame_info_t\n");
-       
+
        for (i = 0; i < frame_len; i++) {
                frame_obj = json_object_array_get_idx(data_obj, i);
 
@@ -192,13 +273,19 @@ _read_json(const char *path)
                //printf("\tframe id: %d\n", json_object_get_int(frame_data_obj));
                frame_id = json_object_get_int(frame_data_obj);
 
+               frame_data_obj = json_object_object_get(frame_obj, "frame_duration");
+               if (frame_data_obj)
+                       ani_info->frames[frame_id - 1].frame_duration = json_object_get_int(frame_data_obj);
+               else
+                       ani_info->frames[frame_id - 1].frame_duration = ani_info->interval;
+
                frame_data_obj = json_object_object_get(frame_obj, "led");
                led_len = json_object_array_length(frame_data_obj);
-               
+
                ani_info->frames[frame_id - 1].num_led = led_len;
                ani_info->frames[frame_id - 1].leds = (default_led_info_t *)calloc(sizeof(default_led_info_t), led_len);
                ERROR_CHECK(ani_info->frames[frame_id - 1].leds, goto error, "Failed to alloc for default_led_info_t\n");
-               
+
                for (j = 0; j < led_len; j++) {
                        led_obj = json_object_array_get_idx(frame_data_obj, j);
 
@@ -217,7 +304,7 @@ _read_json(const char *path)
        return ani_info;
 
 error:
-       free(buffer);
+       if (buffer) free(buffer);
        if (ani_info) {
                if (ani_info->frames) {
                        for (i = 0; i < ani_info->num_key_frames; i++) {
@@ -232,16 +319,46 @@ error:
        return NULL;
 }
 
-static int
-_scandir_filter(const struct dirent *dirent)
+int
+_find_directory(const char *path, Eina_List **json_list)
 {
-       if (!strncmp(dirent->d_name, ".", sizeof(".")) ||
-               !strncmp(dirent->d_name, "..", sizeof("..")))
-               return 0;
-       if (!strstr(dirent->d_name, ".json"))
-               return 0;
+       DIR *dir;
+       struct dirent *cur;
+       int count = 0, ret_cnt = 0;
 
-       return 1;
+       dir = opendir(path);
+       if (!dir)
+       {
+               pui_err("Failed to open %s.\n", path);
+               return count;
+       }
+
+       while ((cur = readdir(dir)) != NULL)
+       {
+               char next_path[MAX_STR] = {0, };
+               if (cur->d_type == DT_DIR)
+               {
+                       if (!strncmp(cur->d_name, ".", sizeof(".")) ||
+                               !strncmp(cur->d_name, "..", sizeof("..")))
+                               continue;
+
+                       snprintf(next_path, MAX_STR, "%s/%s", path, cur->d_name);
+                       ret_cnt = _find_directory(next_path, json_list);
+                       count += ret_cnt;
+               }
+               else
+               {
+                       if (strstr(cur->d_name, ".json"))
+                       {
+                               snprintf(next_path, MAX_STR, "%s/%s", path, cur->d_name);
+                               *json_list = eina_list_append(*json_list, eina_stringshare_add(next_path));
+                               count++;
+                       }
+               }
+       }
+       closedir(dir);
+
+       return count;
 }
 
 
@@ -250,39 +367,44 @@ _create_ani_collection(void)
 {
        pui_int_error e = PUI_INT_ERROR_NONE;
        default_ani_info *ani_info;
-       struct dirent **files;
-       int count, i;
-       char file_path[MAX_STR] = {0, };
+       Eina_List *json_list = NULL;
+       Eina_List *l, *l_next;
+       Eina_Stringshare *path;
 
        // load and store all of animation data
 
-       if ((count = scandir(ANI_COLLECTION_DIR, &files, _scandir_filter, alphasort)) == -1) {
-               printf("Failed to get %s directory (%s)\n", ANI_COLLECTION_DIR, strerror(errno));
-               e = PUI_INT_ERROR_INVALID_RESOURCES;
-               return e;
-       }
-
-       for (i = 0; i < count; i++) {
-               snprintf(file_path, sizeof(file_path), "%s%s", ANI_COLLECTION_DIR, files[i]->d_name);
+       _find_directory(ANI_COLLECTION_DIR, &json_list);
 
-               ani_info = _read_json(file_path);
+       EINA_LIST_FOREACH_SAFE(json_list, l, l_next, path)
+       {
+               ani_info = _read_json(path);
                if (ani_info) {
                        eina_hash_add(_animations_hash, ani_info->id, ani_info);
-                       printf("Success to load %s animation\n", files[i]->d_name);
+                       pui_info("Success to load %s animation (id: %s)\n", path, ani_info->id);
                }
-               memset(file_path, 0, sizeof(file_path));
-       }
-
-       for (i = 0; i < count; i++) {
-               free(files[i]);
+               eina_stringshare_del(path);
+               json_list = eina_list_remove_list(json_list, l);
        }
-       free(files);
 
        //TODO
 
        return e;
 }
 
+pui_bool
+_geometry_get(int *width, int *height)
+{
+       if (!width || !height)
+               return 0;
+
+       if (width)
+               *width = DEFAULT_BACKEND_GEOM_WIDTH;
+       if (height)
+               *height = DEFAULT_BACKEND_GEOM_HEIGHT;
+
+       return 1;
+}
+
 pui_int_error
 _is_ani_supported(pui_id id)
 {
@@ -296,7 +418,9 @@ _is_ani_supported(pui_id id)
                return e;
        }
        ani_info = eina_hash_find(_animations_hash, id);
-       if (!ani_info) e = PUI_INT_ERROR_ID_NOT_SUPPORTED;
+
+       if (!ani_info)
+               e = PUI_INT_ERROR_ID_NOT_SUPPORTED;
 
        return e;
 }
@@ -306,25 +430,26 @@ _ani_info_cleanup(default_ani_info *ani_info)
 {
        int i;
 
-       if (!ani_info) return;
+       if (!ani_info)
+               return;
 
-       eina_hash_del(_animations_hash, ani_info->id, ani_info);
-       if (ani_info->frames) {
-               for (i = 0; i < ani_info->num_key_frames; i++) {
+       if (ani_info->frames)
+       {
+               for (i = 0; i < ani_info->num_key_frames; i++)
+               {
                        if (ani_info->frames[i].leds)
                                free(ani_info->frames[i].leds);
                }
+
                free(ani_info->frames);
        }
+
        free(ani_info->id);
-       free(ani_info);
 }
 
 pui_backend_ani_data *
 _ani_create(pui_id id)
 {
-       pui_int_error e = PUI_INT_ERROR_NONE;
-
        pui_backend_ani_data *ani_data = NULL;
        pui_backend_ani_func *ani_func = NULL;
 
@@ -332,6 +457,11 @@ _ani_create(pui_id id)
        default_ani_info *ani_info = NULL;
 
        //TODO : return NULL if the animation correspond to the given id dones't exist.
+       if (PUI_INT_ERROR_NONE != _is_ani_supported(id))
+       {
+               pui_err("The animation(%s) doesn't supported !\n", id);
+               return NULL;
+       }
 
        /* allocation of the structure of function pointers that will be called from pui_ani_control() */
        ani_func = pui_backend_ani_alloc_ani_func();
@@ -342,48 +472,97 @@ _ani_create(pui_id id)
                return NULL;
        }
 
-       /* Assign each function pointer that corresponds to the given id if needed. */
-       ani_func->ani_start = _ani_start;
-       ani_func->ani_stop = _ani_stop;
-
-       ani_func->reserved1 = NULL;
-       ani_func->reserved2 = NULL;
-       ani_func->reserved3 = NULL;
-       ani_func->reserved4 = NULL;
-       ani_func->reserved5 = NULL;
-       ani_func->reserved6 = NULL;
-       ani_func->reserved7 = NULL;
-       ani_func->reserved8 = NULL;
-       ani_func->reserved9 = NULL;
-       ani_func->reserved10 = NULL;
-
-       /* backend's animation specific info */
-       ani_info = (default_ani_info *)calloc(1, sizeof(default_ani_info));
+       /* get animation info associate with the given id from animation collection */
+       ani_info = get_ani_info_from_ani_collection(id);
 
        if (!ani_info)
        {
-               pui_err("Failed to allocate memory ! (backend's ani specific info)\n");
-               goto err;
-       }
-
-       /* fill animation info associate with the given id from animation collection */
-       e = get_ani_info_from_ani_collection(ani_info, id);
-       
-       if (PUI_INT_ERROR_NONE != e)
-       {
                pui_err("Failed to get ani info from animation collection !\n");
                goto err;
        }
 
        /* allocate backend ani_data and return it to pui ani core */
        ani_data = (pui_backend_ani_data *)calloc(1, sizeof(pui_backend_ani_data));
-       
+
        if (!ani_data)
        {
                pui_err("Failed to allocate memory for pui backend ani data !\n");
                goto err;
        }
-       
+
+       /* Assign each function pointer that corresponds to the given id if needed. */
+       if (!strncmp(ani_info->id, "system/easy_setup", sizeof("system/easy_setup")))
+       {
+               pui_default_backend_ani_easysetup_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "system/processing", sizeof("system/processing")))
+       {
+               pui_default_backend_ani_system_processing_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "system/sw_update_done", sizeof("system/sw_update_done")))
+       {
+               pui_default_backend_ani_swupdatedone_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "system/mic_off", sizeof("system/mic_off")))
+       {
+               pui_default_backend_ani_micoff_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "voice/listening", sizeof("voice/listening")))
+       {
+               pui_default_backend_ani_listening_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "voice/streaming", sizeof("voice/streaming")))
+       {
+               pui_default_backend_ani_streaming_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "voice/processing", sizeof("voice/processing")))
+       {
+               pui_default_backend_ani_processing_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "voice/speaking", sizeof("voice/speaking")))
+       {
+               pui_default_backend_ani_speaking_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "voice/timeout", sizeof("voice/timeout")))
+       {
+               pui_default_backend_ani_timeout_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "notification/normal", sizeof("notification/normal")))
+       {
+               pui_default_backend_ani_normal_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "notification/emergency", sizeof("notification/emergency")))
+       {
+               pui_default_backend_ani_emergency_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "notification/network_error", sizeof("notification/network_error")))
+       {
+               pui_default_backend_ani_networkerror_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "notification/error", sizeof("notification/error")))
+       {
+               pui_default_backend_ani_error_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "notification/alarm", sizeof("notification/alarm")))
+       {
+               pui_default_backend_ani_alarm_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "bt/pairing", sizeof("bt/pairing")))
+       {
+               pui_default_backend_ani_pairing_func_set(ani_func);
+       }
+       else if (!strncmp(ani_info->id, "bt/connected", sizeof("bt/connected")))
+       {
+               pui_default_backend_ani_connected_func_set(ani_func);
+       }
+       else
+       {
+               pui_info("%s animation has no animation handler, using default handler\n", ani_info->id);
+               /* Assign each function pointer that corresponds to the given id if needed. */
+               ani_func->ani_start = _ani_start;
+               ani_func->ani_stop = _ani_stop;
+       }
+
        ani_data->ani_func = ani_func;
        ani_data->ani_info = (pui_backend_ani_info *)ani_info;
 
@@ -398,11 +577,6 @@ err:
                ani_func = NULL;
        }
 
-       if (ani_info)
-       {
-               _ani_info_cleanup(ani_info);
-       }
-
        return NULL;
 }
 
@@ -412,24 +586,19 @@ _ani_destroy(pui_backend_ani_data *ani_data)
        if (!ani_data)
                return;
 
-       pui_backend_ani_free_ani_func(ani_data->ani_func);
-
-       //TODO : free if anything needs to be done with ani_info
-       free(ani_data->ani_info);
-
-       ani_data->ani_func = NULL;
-       if (ani_data->ani_info) {
-               _ani_info_cleanup(ani_data->ani_info);
-               ani_data->ani_info = NULL;
+       if (ani_data->ani_func)
+       {
+               pui_backend_ani_free_ani_func(ani_data->ani_func);
+               ani_data->ani_func = NULL;
        }
 
+       ani_data->ani_info = NULL;
        g_ani_data = NULL;
 }
 
 static void
 _animation_data_free_cb(void *data)
 {
-       int i;
        default_ani_info *ani_info = (default_ani_info *)data;
 
        _ani_info_cleanup(ani_info);
@@ -449,12 +618,13 @@ pui_default_backend_init(void)
        }
 
        backend_data->create_ani_collection = _create_ani_collection;
+       backend_data->geometry_get = _geometry_get;
        backend_data->ani_create = _ani_create;
        backend_data->ani_destroy = _ani_destroy;
 
        /* Allocate backend specific data if needed. Now it will be empty. */
        backend_data->data = NULL;
-       _animations_hash = eina_hash_string_superfast_new(_animation_data_free_cb);
+       _animations_hash = eina_hash_string_superfast_new(NULL);
 
        return backend_data;
 }
@@ -462,6 +632,9 @@ pui_default_backend_init(void)
 static void
 pui_default_backend_deinit(pui_backend_module_data *backend_data)
 {
+       Eina_Iterator *it;
+       default_ani_info *ani_info = NULL;
+
        if (!backend_data)
                return;
 
@@ -480,14 +653,27 @@ pui_default_backend_deinit(pui_backend_module_data *backend_data)
                        g_ani_data->ani_func = NULL;
                }
 
-               if (g_ani_data->ani_info)
+               g_ani_data->ani_info = NULL;
+       }
+
+       if (_animations_hash)
+       {
+               it = eina_hash_iterator_data_new(_animations_hash);
+
+               EINA_ITERATOR_FOREACH(it, ani_info)
                {
-                       _ani_info_cleanup(g_ani_data->ani_info);
-                       g_ani_data->ani_info = NULL;
+                       _animation_data_free_cb(ani_info);
+                       free(ani_info);
                }
+
+               eina_iterator_free(it);
+
+               eina_hash_free(_animations_hash);
+               _animations_hash = NULL;
        }
 
        backend_data->create_ani_collection = NULL;
+       backend_data->geometry_get = NULL;
        backend_data->ani_create = NULL;
        backend_data->ani_destroy = NULL;