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
28 #include <PUI_backend.h>
30 #include <json-c/json.h>
37 #define ANI_COLLECTION_DIR "/usr/share/pui/"
40 #define ERROR_CHECK(exp, action, fmt, ...) \
44 printf(fmt, ##__VA_ARGS__); \
49 pui_backend_ani_func *ani_func = NULL;
50 Eina_Hash *_animations_hash = NULL;
62 typedef struct _default_ani_info default_ani_info;
63 typedef struct _default_frame_info_t default_frame_info_t;
64 typedef struct _default_led_info_t default_led_info_t;
66 struct _default_ani_info
69 pui_ani_status status;
70 pui_ani_control_buffer *buffer;
73 unsigned int key_frame_idx;
74 unsigned int num_key_frames;
75 default_frame_info_t *frames;
77 pui_effect_func effect_func;
80 struct _default_frame_info_t
82 default_led_info_t *leds;
86 struct _default_led_info_t
91 pui_backend_ani_data *g_ani_data = NULL;
94 _ani_backend_frame_cb(void *data, int serial)
96 pui_int_error e = PUI_INT_ERROR_NONE;
97 pui_ani_t *ani = (pui_ani_t *)data;
98 pui_backend_ani_data *ani_data = NULL;
99 pui_ani_control_buffer *buffer = NULL;
102 ani_data = pui_backend_ani_get_ani_data(ani);
103 default_ani_info *ani_info = (default_ani_info *)ani_data->ani_info;
105 now = ecore_time_unix_get();
107 pui_info("[time:%.3f] serial=%d\n", now, serial);
109 /* TODO : make use of ani_info */
112 buffer = pui_backend_ani_get_buffer(ani);
116 pui_err("Failed to get buffer !\n");
121 for(int i = 0; i<12; i++)
123 buffer->ptr[4*i] = 0;
124 buffer->ptr[4*i + 1] = (ani_info->frames[ani_info->key_frame_idx].leds[i].color & 0xFF0000) >> 16;//R
125 buffer->ptr[4*i + 2] = (ani_info->frames[ani_info->key_frame_idx].leds[i].color & 0x00FF00) >> 8;//G
126 buffer->ptr[4*i + 3] = ani_info->frames[ani_info->key_frame_idx].leds[i].color & 0x0000FF;//B
129 e = pui_backend_ani_set_buffer(ani, buffer);
131 if (e != PUI_INT_ERROR_NONE)
133 pui_err("Failed on setting buffer on animation !(e=%d)\n", e);
137 e = pui_backend_ani_update(ani);
139 if (e != PUI_INT_ERROR_NONE)
141 pui_err("Failed on updating animation !(e=%d)\n", e);
145 pui_info("... update (serial=%d)\n", serial);
151 get_ani_info_from_ani_collection(pui_id id)
153 default_ani_info *ani_info = NULL;
155 if (!_animations_hash)
158 pui_info("... id: %s\n", id);
160 ani_info = eina_hash_find(_animations_hash, id);
164 pui_err("ani_info has NOT been found ! (id:%s)\n", id);
168 pui_info("ani_info has been found ! (id:%s)\n", id);
174 _ani_start(pui_ani_t *ani, int repeat)
177 pui_int_error e = PUI_INT_ERROR_NONE;
178 pui_backend_ani_data *ani_data = NULL;
180 ani_data = pui_backend_ani_get_ani_data(ani);
181 default_ani_info *ani_info = (default_ani_info *)ani_data->ani_info;
183 pui_info("... info->id: %s, repeat : %d\n", ani_info->id, repeat);
185 pui_backend_ani_status_update(ani, PUI_ANI_STATUS_STARTED);
186 ret = pui_backend_ani_add_frame_cb(ani, _ani_backend_frame_cb, (double)ani_info->interval / 1000);
190 pui_err("Failed to add frame callback !\n");
191 e = PUI_INT_ERROR_INVALID_RESOURCES;
198 _ani_stop(pui_ani_t *ani)
200 pui_int_error e = PUI_INT_ERROR_NONE;
201 pui_backend_ani_data *ani_data = NULL;
203 ani_data = pui_backend_ani_get_ani_data(ani);
204 default_ani_info *info = (default_ani_info *)ani_data->ani_info;
209 pui_info("... info->id: %s\n", info->id);
211 pui_backend_ani_remove_frame_cb(ani);
212 pui_backend_ani_status_update(ani, PUI_ANI_STATUS_STOPPED);
218 _read_json_file(const char *path, int *data_size)
220 FILE *fp = fopen(path, "rb");
223 ERROR_CHECK(fp, return NULL, "Failed to open file: %s\n", path);
225 fseek(fp, 0, SEEK_END);
227 fseek(fp, 0, SEEK_SET);
229 buffer = (char *)calloc(sizeof(char), size + 1);
231 if (fread(buffer, size, 1, fp) < 1) {
243 static default_ani_info *
244 _read_json(const char *path)
247 json_object *root_obj, *data_obj, *frame_obj, *frame_data_obj, *led_obj, *led_data_obj;
248 default_ani_info *ani_info = NULL;
249 int frame_id = 0, frame_len = 0, led_id = 0, led_len = 0;
250 int data_size = 0, i, j;
252 buffer = _read_json_file(path, &data_size);
253 ERROR_CHECK(buffer && data_size > 0, return EINA_FALSE, "File %s has no data\n", path);
254 root_obj = json_tokener_parse(buffer);
255 ERROR_CHECK(root_obj, goto error, "Failed to tokenize json object\n");
257 ani_info = (default_ani_info *)calloc(1, sizeof(default_ani_info));
258 ERROR_CHECK(ani_info, goto error, "Failed to alloc for animation info\n");
260 data_obj = json_object_object_get(root_obj, "type");
261 //printf("type: %s\n", json_object_get_string(data_obj));
262 type = (char *)json_object_get_string(data_obj);
263 ani_info->id = strndup(type, strlen(type));
265 data_obj = json_object_object_get(root_obj, "interval");
266 //printf("interval: %d\n", json_object_get_int(data_obj));
267 ani_info->interval = json_object_get_int(data_obj);
269 data_obj = json_object_object_get(root_obj, "frame");
270 frame_len = json_object_array_length(data_obj);
272 ani_info->num_key_frames = frame_len;
273 ani_info->frames = (default_frame_info_t *)calloc(sizeof(default_frame_info_t), frame_len);
274 ERROR_CHECK(ani_info->frames, goto error, "Failed to alloc for default_frame_info_t\n");
276 for (i = 0; i < frame_len; i++) {
277 frame_obj = json_object_array_get_idx(data_obj, i);
279 frame_data_obj = json_object_object_get(frame_obj, "frame_id");
280 //printf("\tframe id: %d\n", json_object_get_int(frame_data_obj));
281 frame_id = json_object_get_int(frame_data_obj);
283 frame_data_obj = json_object_object_get(frame_obj, "led");
284 led_len = json_object_array_length(frame_data_obj);
286 ani_info->frames[frame_id - 1].num_led = led_len;
287 ani_info->frames[frame_id - 1].leds = (default_led_info_t *)calloc(sizeof(default_led_info_t), led_len);
288 ERROR_CHECK(ani_info->frames[frame_id - 1].leds, goto error, "Failed to alloc for default_led_info_t\n");
290 for (j = 0; j < led_len; j++) {
291 led_obj = json_object_array_get_idx(frame_data_obj, j);
293 led_data_obj = json_object_object_get(led_obj, "id");
294 //printf("\t\tid: %2d ", json_object_get_int(led_data_obj));
295 led_id = json_object_get_int(led_data_obj);
297 led_data_obj = json_object_object_get(led_obj, "color");
298 //printf("color: %s\n", json_object_get_string(led_data_obj));
299 ani_info->frames[frame_id - 1].leds[led_id - 1].color =
300 strtol(json_object_get_string(led_data_obj), NULL, 16);
310 if (ani_info->frames) {
311 for (i = 0; i < ani_info->num_key_frames; i++) {
312 if (ani_info->frames[i].leds)
313 free(ani_info->frames[i].leds);
315 free(ani_info->frames);
324 _scandir_filter(const struct dirent *dirent)
326 if (!strncmp(dirent->d_name, ".", sizeof(".")) ||
327 !strncmp(dirent->d_name, "..", sizeof("..")))
329 if (!strstr(dirent->d_name, ".json"))
337 _create_ani_collection(void)
339 pui_int_error e = PUI_INT_ERROR_NONE;
340 default_ani_info *ani_info;
341 struct dirent **files;
343 char file_path[MAX_STR] = {0, };
345 // load and store all of animation data
347 if ((count = scandir(ANI_COLLECTION_DIR, &files, _scandir_filter, alphasort)) == -1) {
348 printf("Failed to get %s directory (%s)\n", ANI_COLLECTION_DIR, strerror(errno));
349 e = PUI_INT_ERROR_INVALID_RESOURCES;
353 for (i = 0; i < count; i++) {
354 snprintf(file_path, sizeof(file_path), "%s%s", ANI_COLLECTION_DIR, files[i]->d_name);
356 ani_info = _read_json(file_path);
358 eina_hash_add(_animations_hash, ani_info->id, ani_info);
359 printf("Success to load %s animation\n", files[i]->d_name);
363 for (i = 0; i < count; i++) {
374 _is_ani_supported(pui_id id)
376 pui_int_error e = PUI_INT_ERROR_NONE;
377 default_ani_info *ani_info;
380 /* if the given id is not supported, return PUI_INT_ERROR_ID_NOT_SUPPORTED. */
382 e = PUI_INT_ERROR_ID_NOT_SUPPORTED;
385 ani_info = eina_hash_find(_animations_hash, id);
388 e = PUI_INT_ERROR_ID_NOT_SUPPORTED;
394 _ani_info_cleanup(default_ani_info *ani_info)
401 if (ani_info->frames)
403 for (i = 0; i < ani_info->num_key_frames; i++)
405 if (ani_info->frames[i].leds)
406 free(ani_info->frames[i].leds);
409 free(ani_info->frames);
415 pui_backend_ani_data *
416 _ani_create(pui_id id)
418 pui_backend_ani_data *ani_data = NULL;
419 pui_backend_ani_func *ani_func = NULL;
421 /* backend's animation specific info */
422 default_ani_info *ani_info = NULL;
424 //TODO : return NULL if the animation correspond to the given id dones't exist.
425 if (PUI_INT_ERROR_NONE != _is_ani_supported(id))
427 pui_err("The animation(%s) doesn't supported !\n", id);
431 /* allocation of the structure of function pointers that will be called from pui_ani_control() */
432 ani_func = pui_backend_ani_alloc_ani_func();
436 pui_err("Failed to allocate memory ! (pui backend ani func)\n");
440 /* Assign each function pointer that corresponds to the given id if needed. */
441 ani_func->ani_start = _ani_start;
442 ani_func->ani_stop = _ani_stop;
444 /* get animation info associate with the given id from animation collection */
445 ani_info = get_ani_info_from_ani_collection(id);
449 pui_err("Failed to get ani info from animation collection !\n");
453 /* allocate backend ani_data and return it to pui ani core */
454 ani_data = (pui_backend_ani_data *)calloc(1, sizeof(pui_backend_ani_data));
458 pui_err("Failed to allocate memory for pui backend ani data !\n");
462 ani_data->ani_func = ani_func;
463 ani_data->ani_info = (pui_backend_ani_info *)ani_info;
465 g_ani_data = ani_data;
472 pui_backend_ani_free_ani_func(ani_func);
480 _ani_destroy(pui_backend_ani_data *ani_data)
485 if (ani_data->ani_func)
487 pui_backend_ani_free_ani_func(ani_data->ani_func);
488 ani_data->ani_func = NULL;
491 ani_data->ani_info = NULL;
496 _animation_data_free_cb(void *data)
498 default_ani_info *ani_info = (default_ani_info *)data;
500 _ani_info_cleanup(ani_info);
503 static pui_backend_module_data *
504 pui_default_backend_init(void)
506 pui_backend_module_data *backend_data = NULL;
508 backend_data = (pui_backend_module_data *)calloc(1, sizeof(pui_backend_module_data));
512 pui_err("Failed to allocate memory for pui backend module data !\n");
516 backend_data->create_ani_collection = _create_ani_collection;
517 backend_data->ani_create = _ani_create;
518 backend_data->ani_destroy = _ani_destroy;
520 /* Allocate backend specific data if needed. Now it will be empty. */
521 backend_data->data = NULL;
522 _animations_hash = eina_hash_string_superfast_new(NULL);
528 pui_default_backend_deinit(pui_backend_module_data *backend_data)
531 default_ani_info *ani_info = NULL;
536 if (backend_data->data)
538 //TODO : free variables of backend_data
540 free(backend_data->data);
545 if (g_ani_data->ani_func)
547 pui_backend_ani_free_ani_func(g_ani_data->ani_func);
548 g_ani_data->ani_func = NULL;
551 g_ani_data->ani_info = NULL;
554 if (_animations_hash)
556 it = eina_hash_iterator_data_new(_animations_hash);
558 EINA_ITERATOR_FOREACH(it, ani_info)
560 _animation_data_free_cb(ani_info);
564 eina_iterator_free(it);
566 eina_hash_free(_animations_hash);
567 _animations_hash = NULL;
570 backend_data->create_ani_collection = NULL;
571 backend_data->ani_create = NULL;
572 backend_data->ani_destroy = NULL;
578 pui_backend_module pui_backend_module_info = {
579 "Tizen Reference Speaker Backend",
581 PUI_BACKEND_SET_ABI_VERSION(1, 0),
582 pui_default_backend_init,
583 pui_default_backend_deinit