#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)
+
+pui_backend_ani_func *ani_func = NULL;
+Eina_Hash *_animations_hash = NULL;
+
typedef enum
{
None,
} 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
{
pui_id id;
unsigned int key_frame_idx;
unsigned int num_key_frames;
- double interval;
+ default_frame_info_t *frames;
+ int interval;
pui_effect_func effect_func;
};
+struct _default_frame_info_t
+{
+ default_led_info_t *leds;
+ int num_led;
+};
+
+struct _default_led_info_t
+{
+ unsigned int color;
+};
+
pui_backend_ani_data *g_ani_data = NULL;
static pui_bool
return e;
}
+static char *
+_read_json_file(const char *path, int *data_size)
+{
+ FILE *fp = fopen(path, "rb");
+ int size;
+ char *buffer;
+ ERROR_CHECK(fp, return NULL, "Failed to open file: %s\n", path);
+
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
+ buffer = (char *)calloc(sizeof(char), size + 1);
+
+ if (fread(buffer, size, 1, fp) < 1) {
+ *data_size = 0;
+ free(buffer);
+ fclose(fp);
+ return NULL;
+ }
+
+ *data_size = size;
+ fclose(fp);
+ return buffer;
+}
+
+static default_ani_info *
+_read_json(const char *path)
+{
+ char *buffer, *type;
+ json_object *root_obj, *data_obj, *frame_obj, *frame_data_obj, *led_obj, *led_data_obj;
+ default_ani_info *ani_info = NULL;
+ int frame_id = 0, frame_len = 0, led_id = 0, led_len = 0;
+ 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);
+ root_obj = json_tokener_parse(buffer);
+ ERROR_CHECK(root_obj, goto error, "Failed to tokenize json object\n");
+
+ ani_info = (default_ani_info *)calloc(1, sizeof(default_ani_info));
+ ERROR_CHECK(ani_info, goto error, "Failed to alloc for animation info\n");
+
+ data_obj = json_object_object_get(root_obj, "type");
+ //printf("type: %s\n", json_object_get_string(data_obj));
+ type = (char *)json_object_get_string(data_obj);
+ ani_info->id = strndup(type, strlen(type));
+
+ data_obj = json_object_object_get(root_obj, "interval");
+ //printf("interval: %d\n", json_object_get_int(data_obj));
+ ani_info->interval = json_object_get_int(data_obj);
+
+ data_obj = json_object_object_get(root_obj, "frame");
+ frame_len = json_object_array_length(data_obj);
+
+ 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);
+
+ frame_data_obj = json_object_object_get(frame_obj, "frame_id");
+ //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, "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);
+
+ led_data_obj = json_object_object_get(led_obj, "id");
+ //printf("\t\tid: %2d ", json_object_get_int(led_data_obj));
+ led_id = json_object_get_int(led_data_obj);
+
+ led_data_obj = json_object_object_get(led_obj, "color");
+ //printf("color: %s\n", json_object_get_string(led_data_obj));
+ ani_info->frames[frame_id - 1].leds[led_id - 1].color =
+ strtol(json_object_get_string(led_data_obj), NULL, 16);
+ }
+ }
+
+ free(buffer);
+ return ani_info;
+
+error:
+ free(buffer);
+ if (ani_info) {
+ 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);
+ }
+ return NULL;
+}
+
+static int
+_scandir_filter(const struct dirent *dirent)
+{
+ if (!strncmp(dirent->d_name, ".", sizeof(".")) ||
+ !strncmp(dirent->d_name, "..", sizeof("..")))
+ return 0;
+ if (!strstr(dirent->d_name, ".json"))
+ return 0;
+
+ return 1;
+}
+
+
pui_int_error
_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, };
+
+ // 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);
+
+ ani_info = _read_json(file_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);
+ }
+ memset(file_path, 0, sizeof(file_path));
+ }
+
+ for (i = 0; i < count; i++) {
+ free(files[i]);
+ }
+ free(files);
//TODO
_is_ani_supported(pui_id id)
{
pui_int_error e = PUI_INT_ERROR_NONE;
+ default_ani_info *ani_info;
//TODO
/* if the given id is not supported, return PUI_INT_ERROR_ID_NOT_SUPPORTED. */
+ if (!id) {
+ e = PUI_INT_ERROR_ID_NOT_SUPPORTED;
+ return e;
+ }
+ ani_info = eina_hash_find(_animations_hash, id);
+ if (!ani_info) e = PUI_INT_ERROR_ID_NOT_SUPPORTED;
return e;
}
+static void
+_ani_info_cleanup(default_ani_info *ani_info)
+{
+ int i;
+
+ 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[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)
{
if (ani_info)
{
- //TODO : free if anything needs to be done with ani_info
-
- free(ani_info);
+ _ani_info_cleanup(ani_info);
}
return NULL;
free(ani_data->ani_info);
ani_data->ani_func = NULL;
- ani_data->ani_info = NULL;
+ if (ani_data->ani_info) {
+ _ani_info_cleanup(ani_data->ani_info);
+ 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);
+}
+
static pui_backend_module_data *
pui_default_backend_init(void)
{
/* 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);
return backend_data;
}
if (g_ani_data->ani_info)
{
- //TODO : free if anything needs to be done with ani_info
- free(g_ani_data->ani_info);
+ _ani_info_cleanup(g_ani_data->ani_info);
g_ani_data->ani_info = NULL;
}
}