default_backend: remove duplicate code
[platform/core/uifw/libpui.git] / backends / default_backend.c
1 /*
2  * Copyright © 2019 Samsung Electronics co., Ltd. All Rights Reserved.
3  *
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:
11  *
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.
15  *
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
23  * SOFTWARE.
24  */
25
26 #include "default_backend.h"
27 #include <limits.h>
28
29 pui_backend_ani_func *ani_func = NULL;
30 Eina_Hash *_animations_hash = NULL;
31 pui_backend_ani_data *g_ani_data = NULL;
32
33 #if 0
34 static double
35 _ani_backend_ease_function_get_intensity(pui_effect_func func, double interval)
36 {
37         double intensity = interval;
38         switch (func)
39         {
40                 case None:
41                         break;
42                 case Linear:
43                         break;
44                 case EaseInSine:
45                         intensity = 1 - cos(PI / 2 * interval);
46                         break;
47                 case EaseOutSine:
48                         intensity = sin(PI / 2 * interval);
49                         break;
50                 case EaseInQuart:
51                         intensity = interval * interval;
52                         break;
53                 case EaseOutQuart:
54                         intensity = interval * (2 - interval);
55                         break;
56                 default:
57                         break;
58         }
59
60         return intensity;
61 }
62
63 static unsigned int
64 _ani_backend_get_value(unsigned int end_frame, unsigned int start_frame, double interval)
65 {
66         double res = 0.0;
67
68         // interval: frame ratio between key frame to key frame
69         // end_frame and start_frame is key frame
70
71         res = (end_frame - start_frame) * interval + start_frame;
72
73         return res;
74 }
75 #endif
76
77 static pui_bool
78 _ani_backend_frame_cb(void *data, int serial)
79 {
80         pui_int_error e = PUI_INT_ERROR_NONE;
81         pui_ani_t *ani = (pui_ani_t *)data;
82         pui_backend_ani_data *ani_data = NULL;
83         pui_ani_control_buffer *buffer = NULL;
84
85         ani_data = pui_backend_ani_get_ani_data(ani);
86         default_ani_info *ani_info = (default_ani_info *)ani_data->ani_info;
87
88         /* TODO : make use of ani_info */
89         (void) ani_info;
90
91         buffer = pui_backend_ani_get_buffer(ani);
92
93         if (!buffer)
94         {
95                 pui_err("Failed to get buffer !\n");
96                 return 0;
97         }
98
99         /* test example */
100         for(int i = 0; i<12; i++)
101         {
102                 buffer->ptr[4*i] = 0;
103                 buffer->ptr[4*i + 1] = (ani_info->frames[ani_info->frame_idx].leds[i].color & LED_MASK_RED) >> 16;//R
104                 buffer->ptr[4*i + 2] = (ani_info->frames[ani_info->frame_idx].leds[i].color & LED_MASK_GREEN) >> 8;//G
105                 buffer->ptr[4*i + 3] = ani_info->frames[ani_info->frame_idx].leds[i].color & LED_MASK_BLUE;//B
106         }
107
108         e = pui_backend_ani_set_buffer(ani, buffer);
109
110         if (e != PUI_INT_ERROR_NONE)
111         {
112                 pui_err("Failed on setting buffer on animation !(e=%d)\n", e);
113                 return (pui_bool)0;
114         }
115
116         e = pui_backend_ani_update(ani);
117
118         if (e != PUI_INT_ERROR_NONE)
119         {
120                 pui_err("Failed on updating animation !(e=%d)\n", e);
121                 return (pui_bool)0;
122         }
123
124         pui_info("... update (serial=%d)\n", serial);
125
126         return (pui_bool)1;
127 }
128
129 default_ani_info *
130 get_ani_info_from_ani_collection(pui_id id)
131 {
132         default_ani_info *ani_info = NULL;
133
134         if (!_animations_hash)
135                 return NULL;
136
137         pui_info("... id: %s\n", id);
138
139         ani_info = eina_hash_find(_animations_hash, id);
140
141         if (!ani_info)
142         {
143                 pui_err("ani_info has NOT been found ! (id:%s)\n", id);
144                 return NULL;
145         }
146
147         pui_info("ani_info has been found ! (id:%s)\n", id);
148
149         return ani_info;
150 }
151
152 pui_error
153 _ani_start(pui_ani_t *ani, int repeat)
154 {
155         pui_bool ret = 0;
156         pui_int_error e = PUI_INT_ERROR_NONE;
157         pui_backend_ani_data *ani_data = NULL;
158
159         ani_data = pui_backend_ani_get_ani_data(ani);
160         default_ani_info *ani_info = (default_ani_info *)ani_data->ani_info;
161
162         pui_info("... info->id: %s, repeat : %d\n", ani_info->id, repeat);
163
164         pui_backend_ani_status_update(ani, PUI_ANI_STATUS_STARTED);
165         ret = pui_backend_ani_add_frame_cb(ani, _ani_backend_frame_cb, (double)ani_info->interval / 1000);
166
167         if (!ret)
168         {
169                 pui_err("Failed to add frame callback !\n");
170                 e = PUI_INT_ERROR_INVALID_RESOURCES;
171         }
172
173         return e;
174 }
175
176 pui_error
177 _ani_stop(pui_ani_t *ani, pui_bool force)
178 {
179         pui_int_error e = PUI_INT_ERROR_NONE;
180         pui_backend_ani_data *ani_data = NULL;
181
182         ani_data = pui_backend_ani_get_ani_data(ani);
183         default_ani_info *info = (default_ani_info *)ani_data->ani_info;
184
185         //TODO
186         (void) info;
187
188         pui_info("... info->id: %s, force=%d\n", info->id, force);
189
190         pui_backend_ani_remove_frame_cb(ani);
191
192         if (force)
193                 pui_backend_ani_status_update(ani, PUI_ANI_STATUS_PAUSED);
194         else
195                 pui_backend_ani_status_update(ani, PUI_ANI_STATUS_STOPPED);
196
197         return e;
198 }
199
200 static char *
201 _read_json_file(const char *path, int *data_size)
202 {
203         FILE *fp = fopen(path, "rb");
204         int size, ret;
205         char *buffer = NULL;
206         ERROR_CHECK(fp, return NULL, "Failed to open file: %s\n", path);
207
208         ret = fseek(fp, 0, SEEK_END);
209         ERROR_CHECK(ret == 0, goto error, "Failed to seek file. ret: %d\n", ret);
210         size = (long int)ftell(fp);
211         ERROR_CHECK(0 < size && size < INT_MAX, goto error, "Invalid file: %d size\n", size);
212         ret = fseek(fp, 0, SEEK_SET);
213         ERROR_CHECK(ret == 0, goto error, "Failed to seek file. ret: %d\n", ret);
214
215         buffer = (char *)calloc(sizeof(char), size + 1);
216         ERROR_CHECK(buffer, goto error, "Failed to allocate memory for buffer\n");
217
218         if (fread(buffer, size, 1, fp) < 1) {
219                 goto error;
220         }
221
222         *data_size = size;
223         fclose(fp);
224         return buffer;
225
226 error:
227         *data_size = 0;
228         if (buffer) free(buffer);
229         fclose(fp);
230         return NULL;
231 }
232
233 static default_ani_info *
234 _read_json(const char *path)
235 {
236         char *buffer, *type;
237         json_object *root_obj, *data_obj, *frame_obj, *frame_data_obj, *led_obj, *led_data_obj;
238         default_ani_info *ani_info = NULL;
239         int frame_id = 0, frame_len = 0, led_id = 0, led_len = 0;
240         int data_size = 0, i, j;
241
242         buffer = _read_json_file(path, &data_size);
243         ERROR_CHECK(buffer && data_size > 0, goto error, "File %s has no data\n", path);
244         root_obj = json_tokener_parse(buffer);
245         ERROR_CHECK(root_obj, goto error, "Failed to tokenize json object\n");
246
247         ani_info = (default_ani_info *)calloc(1, sizeof(default_ani_info));
248         ERROR_CHECK(ani_info, goto error, "Failed to alloc for animation info\n");
249
250         data_obj = json_object_object_get(root_obj, "type");
251         //printf("type: %s\n", json_object_get_string(data_obj));
252         type = (char *)json_object_get_string(data_obj);
253         ani_info->id = strndup(type, strlen(type));
254
255         data_obj = json_object_object_get(root_obj, "interval");
256         //printf("interval: %d\n", json_object_get_int(data_obj));
257         ani_info->interval = json_object_get_int(data_obj);
258
259         data_obj = json_object_object_get(root_obj, "frame");
260         frame_len = json_object_array_length(data_obj);
261
262         ani_info->num_key_frames = frame_len;
263         ani_info->frames = (default_frame_info_t *)calloc(sizeof(default_frame_info_t), frame_len);
264         ERROR_CHECK(ani_info->frames, goto error, "Failed to alloc for default_frame_info_t\n");
265
266         for (i = 0; i < frame_len; i++) {
267                 frame_obj = json_object_array_get_idx(data_obj, i);
268
269                 frame_data_obj = json_object_object_get(frame_obj, "frame_id");
270                 //printf("\tframe id: %d\n", json_object_get_int(frame_data_obj));
271                 frame_id = json_object_get_int(frame_data_obj);
272
273                 frame_data_obj = json_object_object_get(frame_obj, "frame_duration");
274                 if (frame_data_obj)
275                         ani_info->frames[frame_id - 1].frame_duration = json_object_get_int(frame_data_obj);
276                 else
277                         ani_info->frames[frame_id - 1].frame_duration = ani_info->interval;
278
279                 frame_data_obj = json_object_object_get(frame_obj, "led");
280                 led_len = json_object_array_length(frame_data_obj);
281
282                 ani_info->frames[frame_id - 1].num_led = led_len;
283                 if (ani_info->max_leds < led_len) ani_info->max_leds = led_len;
284                 ani_info->frames[frame_id - 1].leds = (default_led_info_t *)calloc(sizeof(default_led_info_t), led_len);
285                 ERROR_CHECK(ani_info->frames[frame_id - 1].leds, goto error, "Failed to alloc for default_led_info_t\n");
286
287                 for (j = 0; j < led_len; j++) {
288                         led_obj = json_object_array_get_idx(frame_data_obj, j);
289
290                         led_data_obj = json_object_object_get(led_obj, "id");
291                         //printf("\t\tid: %2d  ", json_object_get_int(led_data_obj));
292                         led_id = json_object_get_int(led_data_obj);
293
294                         led_data_obj = json_object_object_get(led_obj, "color");
295                         //printf("color: %s\n", json_object_get_string(led_data_obj));
296                         ani_info->frames[frame_id - 1].leds[led_id - 1].color =
297                                 strtol(json_object_get_string(led_data_obj), NULL, 16);
298                 }
299         }
300
301         free(buffer);
302         return ani_info;
303
304 error:
305         if (buffer) free(buffer);
306         if (ani_info) {
307                 if (ani_info->frames) {
308                         for (i = 0; i < ani_info->num_key_frames; i++) {
309                                 if (ani_info->frames[i].leds)
310                                         free(ani_info->frames[i].leds);
311                         }
312                         free(ani_info->frames);
313                 }
314                 free(ani_info->id);
315                 free(ani_info);
316         }
317         return NULL;
318 }
319
320 int
321 _find_directory(const char *path, Eina_List **json_list)
322 {
323         DIR *dir;
324         struct dirent *cur;
325         int count = 0, ret_cnt = 0;
326
327         dir = opendir(path);
328         if (!dir)
329         {
330                 pui_err("Failed to open %s.\n", path);
331                 return count;
332         }
333
334         while ((cur = readdir(dir)) != NULL)
335         {
336                 char next_path[MAX_STR] = {0, };
337                 if (cur->d_type == DT_DIR)
338                 {
339                         if (!strncmp(cur->d_name, ".", sizeof(".")) ||
340                                 !strncmp(cur->d_name, "..", sizeof("..")))
341                                 continue;
342
343                         snprintf(next_path, MAX_STR, "%s/%s", path, cur->d_name);
344                         ret_cnt = _find_directory(next_path, json_list);
345                         count += ret_cnt;
346                 }
347                 else
348                 {
349                         if (strstr(cur->d_name, ".json"))
350                         {
351                                 snprintf(next_path, MAX_STR, "%s/%s", path, cur->d_name);
352                                 *json_list = eina_list_append(*json_list, eina_stringshare_add(next_path));
353                                 count++;
354                         }
355                 }
356         }
357         closedir(dir);
358
359         return count;
360 }
361
362 default_ani_info *
363 _create_default_ani_info(char *type)
364 {
365         default_ani_info *ani_info = NULL;
366         int frame_len = 1;
367         int led_len = 12;
368
369         ani_info = (default_ani_info *)calloc(1, sizeof(default_ani_info));
370         ERROR_CHECK(ani_info, goto error, "Failed to alloc for animation info\n");
371
372         ani_info->id = strndup(type, strlen(type));
373         ani_info->interval = 50;
374
375         ani_info->num_key_frames = frame_len;
376         ani_info->frames = (default_frame_info_t *)calloc(sizeof(default_frame_info_t), frame_len);
377         ERROR_CHECK(ani_info->frames, goto error, "Failed to alloc for default_frame_info_t\n");
378
379         ani_info->frames[0].frame_duration = 500;
380         ani_info->frames[0].num_led = led_len;
381         ani_info->max_leds = led_len;
382         ani_info->frames[0].leds = (default_led_info_t *)calloc(sizeof(default_led_info_t), led_len);
383         ERROR_CHECK(ani_info->frames[0].leds, goto error, "Failed to alloc for default_led_info_t\n");
384
385         return ani_info;
386
387 error:
388         if (ani_info) {
389                 if (ani_info->frames) {
390                         for (int i = 0; i < ani_info->num_key_frames; i++) {
391                                 if (ani_info->frames[i].leds)
392                                         free(ani_info->frames[i].leds);
393                         }
394                         free(ani_info->frames);
395                 }
396                 free(ani_info->id);
397                 free(ani_info);
398         }
399         return NULL;
400 }
401
402
403 pui_int_error
404 _create_ani_collection(void)
405 {
406         pui_int_error e = PUI_INT_ERROR_NONE;
407         default_ani_info *ani_info;
408         Eina_List *json_list = NULL;
409         Eina_List *l, *l_next;
410         Eina_Stringshare *path;
411
412         // load and store all of animation data
413
414         _find_directory(ANI_COLLECTION_DIR, &json_list);
415
416         pui_err("Start create ani collect...\n");
417
418         EINA_LIST_FOREACH_SAFE(json_list, l, l_next, path)
419         {
420                 ani_info = _read_json(path);
421                 if (ani_info) {
422                         eina_hash_add(_animations_hash, ani_info->id, ani_info);
423                         pui_info("Success to load %s animation (id: %s)\n", path, ani_info->id);
424                 }
425                 eina_stringshare_del(path);
426                 json_list = eina_list_remove_list(json_list, l);
427         }
428
429         //TODO
430         ani_info = _create_default_ani_info("default/clear_fadeout");
431         if (ani_info) {
432                 eina_hash_add(_animations_hash, ani_info->id, ani_info);
433                 pui_err("Success to load default animation (id: %s)\n", ani_info->id);
434         }
435         ani_info = _create_default_ani_info("default/clear_immediate");
436         if (ani_info) {
437                 eina_hash_add(_animations_hash, ani_info->id, ani_info);
438                 pui_err("Success to load default animation (id: %s)\n", ani_info->id);
439         }
440
441         pui_err("End create ani collect...\n");
442
443         return e;
444 }
445
446 pui_bool
447 _geometry_get(int *width, int *height)
448 {
449         if (!width || !height)
450                 return 0;
451
452         if (width)
453                 *width = DEFAULT_BACKEND_GEOM_WIDTH;
454         if (height)
455                 *height = DEFAULT_BACKEND_GEOM_HEIGHT;
456
457         return 1;
458 }
459
460 pui_int_error
461 _is_ani_supported(pui_id id)
462 {
463         pui_int_error e = PUI_INT_ERROR_NONE;
464         default_ani_info *ani_info;
465
466         //TODO
467         /* if the given id is not supported, return PUI_INT_ERROR_ID_NOT_SUPPORTED. */
468         if (!id) {
469                 e = PUI_INT_ERROR_ID_NOT_SUPPORTED;
470                 return e;
471         }
472         ani_info = eina_hash_find(_animations_hash, id);
473
474         if (!ani_info)
475                 e = PUI_INT_ERROR_ID_NOT_SUPPORTED;
476
477         return e;
478 }
479
480 static void
481 _ani_info_cleanup(default_ani_info *ani_info)
482 {
483         int i;
484
485         if (!ani_info)
486                 return;
487
488         if (ani_info->frames)
489         {
490                 for (i = 0; i < ani_info->num_key_frames; i++)
491                 {
492                         if (ani_info->frames[i].leds)
493                                 free(ani_info->frames[i].leds);
494                 }
495
496                 free(ani_info->frames);
497         }
498
499         free(ani_info->id);
500 }
501
502 pui_backend_ani_data *
503 _ani_create(pui_id id)
504 {
505         pui_backend_ani_data *ani_data = NULL;
506         pui_backend_ani_func *ani_func = NULL;
507
508         /* backend's animation specific info */
509         default_ani_info *ani_info = NULL;
510
511         //TODO : return NULL if the animation correspond to the given id dones't exist.
512         if (PUI_INT_ERROR_NONE != _is_ani_supported(id))
513         {
514                 pui_err("The animation(%s) doesn't supported !\n", id);
515                 return NULL;
516         }
517
518         /* allocation of the structure of function pointers that will be called from pui_ani_control() */
519         ani_func = pui_backend_ani_alloc_ani_func();
520
521         if (!ani_func)
522         {
523                 pui_err("Failed to allocate memory ! (pui backend ani func)\n");
524                 return NULL;
525         }
526
527         /* get animation info associate with the given id from animation collection */
528         ani_info = get_ani_info_from_ani_collection(id);
529
530         if (!ani_info)
531         {
532                 pui_err("Failed to get ani info from animation collection !\n");
533                 goto err;
534         }
535
536         /* allocate backend ani_data and return it to pui ani core */
537         ani_data = (pui_backend_ani_data *)calloc(1, sizeof(pui_backend_ani_data));
538
539         if (!ani_data)
540         {
541                 pui_err("Failed to allocate memory for pui backend ani data !\n");
542                 goto err;
543         }
544
545         /* Assign each function pointer that corresponds to the given id if needed. */
546         if (!strncmp(ani_info->id, "system/easy_setup", sizeof("system/easy_setup")))
547         {
548                 pui_default_backend_ani_easysetup_func_set(ani_func);
549         }
550         else if (!strncmp(ani_info->id, "system/processing", sizeof("system/processing")))
551         {
552                 pui_default_backend_ani_system_processing_func_set(ani_func);
553         }
554         else if (!strncmp(ani_info->id, "system/sw_update_done", sizeof("system/sw_update_done")))
555         {
556                 pui_default_backend_ani_swupdatedone_func_set(ani_func);
557         }
558         else if (!strncmp(ani_info->id, "system/mic_off", sizeof("system/mic_off")))
559         {
560                 pui_default_backend_ani_micoff_func_set(ani_func);
561         }
562         else if (!strncmp(ani_info->id, "voice/listening", sizeof("voice/listening")))
563         {
564                 pui_default_backend_ani_listening_func_set(ani_func);
565         }
566         else if (!strncmp(ani_info->id, "voice/streaming", sizeof("voice/streaming")))
567         {
568                 pui_default_backend_ani_streaming_func_set(ani_func);
569         }
570         else if (!strncmp(ani_info->id, "voice/processing", sizeof("voice/processing")))
571         {
572                 pui_default_backend_ani_processing_func_set(ani_func);
573         }
574         else if (!strncmp(ani_info->id, "voice/speaking", sizeof("voice/speaking")))
575         {
576                 pui_default_backend_ani_speaking_func_set(ani_func);
577         }
578         else if (!strncmp(ani_info->id, "voice/timeout", sizeof("voice/timeout")))
579         {
580                 pui_default_backend_ani_timeout_func_set(ani_func);
581         }
582         else if (!strncmp(ani_info->id, "notification/normal", sizeof("notification/normal")))
583         {
584                 pui_default_backend_ani_normal_func_set(ani_func);
585         }
586         else if (!strncmp(ani_info->id, "notification/emergency", sizeof("notification/emergency")))
587         {
588                 pui_default_backend_ani_emergency_func_set(ani_func);
589         }
590         else if (!strncmp(ani_info->id, "notification/network_error", sizeof("notification/network_error")))
591         {
592                 pui_default_backend_ani_networkerror_func_set(ani_func);
593         }
594         else if (!strncmp(ani_info->id, "notification/error", sizeof("notification/error")))
595         {
596                 pui_default_backend_ani_error_func_set(ani_func);
597         }
598         else if (!strncmp(ani_info->id, "notification/alarm", sizeof("notification/alarm")))
599         {
600                 pui_default_backend_ani_alarm_func_set(ani_func);
601         }
602         else if (!strncmp(ani_info->id, "bt/pairing", sizeof("bt/pairing")))
603         {
604                 pui_default_backend_ani_pairing_func_set(ani_func);
605         }
606         else if (!strncmp(ani_info->id, "bt/connected", sizeof("bt/connected")))
607         {
608                 pui_default_backend_ani_connected_func_set(ani_func);
609         }
610         else if (!strncmp(ani_info->id, "default/clear_fadeout", sizeof("default/clear_fadeout")))
611         {
612                 pui_default_backend_ani_clear_fadeout_func_set(ani_func);
613         }
614         else if (!strncmp(ani_info->id, "default/clear_immediate", sizeof("default/clear_immediate")))
615         {
616                 pui_default_backend_ani_clear_immediate_func_set(ani_func);
617         }
618         else
619         {
620                 pui_info("%s animation has no animation handler, using default handler\n", ani_info->id);
621                 /* Assign each function pointer that corresponds to the given id if needed. */
622                 ani_func->ani_start = _ani_start;
623                 ani_func->ani_stop = _ani_stop;
624         }
625
626         ani_data->ani_func = ani_func;
627         ani_data->ani_info = (pui_backend_ani_info *)ani_info;
628
629         g_ani_data = ani_data;
630
631         return ani_data;
632
633 err:
634         if (ani_func)
635         {
636                 pui_backend_ani_free_ani_func(ani_func);
637                 ani_func = NULL;
638         }
639
640         return NULL;
641 }
642
643 void
644 _ani_destroy(pui_backend_ani_data *ani_data)
645 {
646         if (!ani_data)
647                 return;
648
649         if (ani_data->ani_func)
650         {
651                 pui_backend_ani_free_ani_func(ani_data->ani_func);
652                 ani_data->ani_func = NULL;
653         }
654
655         ani_data->ani_info = NULL;
656         g_ani_data = NULL;
657 }
658
659 static void
660 _animation_data_free_cb(void *data)
661 {
662         default_ani_info *ani_info = (default_ani_info *)data;
663
664         _ani_info_cleanup(ani_info);
665 }
666
667 default_frame_info_t *
668 backend_util_alloc_frame(default_ani_info *ani_info)
669 {
670         default_frame_info_t *frame;
671
672         frame = (default_frame_info_t *)calloc(sizeof(default_frame_info_t), 1);
673         ERROR_CHECK(frame, return NULL, "Failed to allocate memory for frame\n");
674
675         frame->leds = (default_led_info_t *)calloc(sizeof(default_led_info_t), ani_info->max_leds);
676         ERROR_CHECK(frame->leds, goto error, "Failed to allocate memory for led\n");
677
678         frame->num_led = ani_info->max_leds;
679
680         return frame;
681
682 error:
683         free(frame);
684         return NULL;
685 }
686
687 void
688 backend_util_cleanup_frame(default_frame_info_t *frame)
689 {
690         ERROR_CHECK(frame, return, "Invalid frame to cleanup\n");
691
692         for (int i = 0; i < frame->num_led; i++)
693         {
694                 frame->leds[i].color = 0x0;
695         }
696         frame->frame_duration = 0;
697 }
698
699 void
700 backend_util_free_frame(default_frame_info_t *frame)
701 {
702         if (!frame) return;
703
704         if (frame->leds) free(frame->leds);
705         free(frame);
706 }
707
708 void
709 pui_default_backend_ani_get_led_rgb(default_frame_info_t *frame,
710                                                                                         int led_idx,
711                                                                                         unsigned int *r,
712                                                                                         unsigned int *g,
713                                                                                         unsigned int *b)
714 {
715         if (!frame) return;
716         if (!r || !g || !b) return;
717         if (led_idx > frame->num_led) return;
718
719         *r = (frame->leds[led_idx].color & LED_MASK_RED) >> 16;
720         *g = (frame->leds[led_idx].color & LED_MASK_GREEN) >> 8;
721         *b = (frame->leds[led_idx].color & LED_MASK_BLUE);
722 }
723
724 int
725 pui_default_backend_ani_update_frame(pui_ani_t *ani,
726                                                                                         pui_backend_ani_data *ani_data,
727                                                                                         pui_ani_control_buffer *buffer,
728                                                                                         default_frame_info_t *frame,
729                                                                                          int serial)
730 {
731         pui_int_error e = PUI_INT_ERROR_NONE;
732         default_ani_info *ani_info = (default_ani_info *)ani_data->ani_info;
733         unsigned int r = 0x0, g = 0x0, b = 0x0;
734
735         for(int i = 0; i<12; i++)
736         {
737                 pui_default_backend_ani_get_led_rgb(frame, i, &r, &g, &b);
738                 buffer->ptr[4*i] = 0;
739                 buffer->ptr[4*i + 1] = b; /* BLUE */
740                 buffer->ptr[4*i + 2] = g; /* GREEN */
741                 buffer->ptr[4*i + 3] = r; /* RED */
742         }
743         backend_util_cleanup_frame(frame);
744
745         e = pui_backend_ani_set_buffer(ani, buffer);
746
747         if (e != PUI_INT_ERROR_NONE)
748         {
749                 pui_err("Failed on setting buffer on animation !(e=%d)\n", e);
750                 return 0;
751         }
752
753         e = pui_backend_ani_update(ani);
754
755         if (e != PUI_INT_ERROR_NONE)
756         {
757                 pui_err("Failed on updating animation !(e=%d)\n", e);
758                 return 0;
759         }
760
761         pui_info("... update (serial=%d), (repeat| cur: %d, want: %d)\n",
762                 serial, ani_info->repeat_cur, ani_info->repeat);
763
764         if (ani_info->repeat >= 0 &&
765                 ani_info->repeat_cur >= ani_info->repeat)
766         {
767                 ani_data->ani_func->ani_stop(ani, EINA_FALSE);
768         }
769
770         return 1;
771 }
772
773 static pui_backend_module_data *
774 pui_default_backend_init(void)
775 {
776         pui_backend_module_data *backend_data = NULL;
777
778         backend_data = (pui_backend_module_data *)calloc(1, sizeof(pui_backend_module_data));
779
780         if (!backend_data)
781         {
782                 pui_err("Failed to allocate memory for pui backend module data !\n");
783                 return NULL;
784         }
785
786         backend_data->create_ani_collection = _create_ani_collection;
787         backend_data->geometry_get = _geometry_get;
788         backend_data->ani_create = _ani_create;
789         backend_data->ani_destroy = _ani_destroy;
790
791         /* Allocate backend specific data if needed. Now it will be empty. */
792         backend_data->data = NULL;
793         _animations_hash = eina_hash_string_superfast_new(NULL);
794
795         return backend_data;
796 }
797
798 static void
799 pui_default_backend_deinit(pui_backend_module_data *backend_data)
800 {
801         Eina_Iterator *it;
802         default_ani_info *ani_info = NULL;
803
804         if (!backend_data)
805                 return;
806
807         if (backend_data->data)
808         {
809                 //TODO : free variables of backend_data
810
811                 free(backend_data->data);
812         }
813
814         if (g_ani_data)
815         {
816                 if (g_ani_data->ani_func)
817                 {
818                         pui_backend_ani_free_ani_func(g_ani_data->ani_func);
819                         g_ani_data->ani_func = NULL;
820                 }
821
822                 g_ani_data->ani_info = NULL;
823         }
824
825         if (_animations_hash)
826         {
827                 it = eina_hash_iterator_data_new(_animations_hash);
828
829                 EINA_ITERATOR_FOREACH(it, ani_info)
830                 {
831                         _animation_data_free_cb(ani_info);
832                         free(ani_info);
833                 }
834
835                 eina_iterator_free(it);
836
837                 eina_hash_free(_animations_hash);
838                 _animations_hash = NULL;
839         }
840
841         backend_data->create_ani_collection = NULL;
842         backend_data->geometry_get = NULL;
843         backend_data->ani_create = NULL;
844         backend_data->ani_destroy = NULL;
845
846         free(backend_data);
847         backend_data = NULL;
848 }
849
850 pui_backend_module pui_backend_module_info = {
851         "Tizen Reference Speaker Backend",
852         "Samsung",
853         PUI_BACKEND_SET_ABI_VERSION(1, 0),
854         pui_default_backend_init,
855         pui_default_backend_deinit
856 };
857