From 60f5ef830f8c5e059572782c748a5e00205fc48a Mon Sep 17 00:00:00 2001 From: jeon Date: Mon, 21 Oct 2019 20:53:37 +0900 Subject: [PATCH] backend: add default clear animations - support fadeout / immediate clear animations Change-Id: I605bc8a094a48a59a111b78462715b975c727bbb --- backends/Makefile.am | 2 + backends/default/default_ani_clear_fadeout.c | 244 +++++++++++++++++++++++++ backends/default/default_ani_clear_immediate.c | 186 +++++++++++++++++++ backends/default_backend.c | 62 +++++++ backends/default_backend.h | 2 + include/PUI.h | 3 + include/PUI_backend.h | 3 + src/PUI.c | 25 +++ src/PUI_ani.c | 18 ++ src/PUI_backend.c | 19 ++ src/PUI_internal.h | 3 + 11 files changed, 567 insertions(+) create mode 100644 backends/default/default_ani_clear_fadeout.c create mode 100644 backends/default/default_ani_clear_immediate.c diff --git a/backends/Makefile.am b/backends/Makefile.am index 3bacb06..41645b2 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -14,6 +14,8 @@ libpui_default_backend_la_LIBADD = $(DEFAULT_BACKEND_LIBS) libpui_default_backend_la_SOURCES = \ default_backend.h \ default_backend.c \ + default/default_ani_clear_fadeout.c \ + default/default_ani_clear_immediate.c \ system/default_ani_easysetup.c \ system/default_ani_system_processing.c \ system/default_ani_swupdatedone.c \ diff --git a/backends/default/default_ani_clear_fadeout.c b/backends/default/default_ani_clear_fadeout.c new file mode 100644 index 0000000..5ed7453 --- /dev/null +++ b/backends/default/default_ani_clear_fadeout.c @@ -0,0 +1,244 @@ +/* + * 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" +static void +_ani_backend_clear_fadeout_get_led_rgb(default_frame_info_t *frame, int led_idx, unsigned int *r, unsigned int *g, unsigned int *b) +{ + if (!frame) return; + if (!r || !g || !b) return; + if (led_idx > frame->num_led) return; + + *r = (frame->leds[led_idx].color & LED_MASK_RED) >> 16; + *g = (frame->leds[led_idx].color & LED_MASK_GREEN) >> 8; + *b = (frame->leds[led_idx].color & LED_MASK_BLUE); +} + +static default_frame_info_t *ani_frame = NULL; + +static default_frame_info_t * +_ani_clear_fadeout_get_frame(default_ani_info *ani_info) +{ + default_frame_info_t *key_frame; + unsigned int r, g, b, r2, g2, b2; + double div; + + if (ani_info->frame_idx == 0) + { + ani_info->frame_max = (unsigned int)(ani_info->frames[0].frame_duration / ani_info->interval); + } + + key_frame = &ani_info->frames[0]; + + div = (double)(ani_info->frame_idx) / (double)ani_info->frame_max; + r = g = b = r2 = g2 = b2 = 0x0; + for (int i = 0; i < key_frame->num_led; i++) + { + _ani_backend_clear_fadeout_get_led_rgb(key_frame, i, &r, &g, &b); + r2 = r - (int)(r * div); + g2 = g - (int)(g * div); + b2 = b - (int)(b * div); + + ani_frame->leds[i].color = (r2 << 16) + (g2 << 8) + (b2); + } + + ani_info->frame_idx++; + if (ani_info->frame_idx > ani_info->frame_max) + { + ani_info->frame_idx = 0; + ani_info->repeat_cur++; + } + + return ani_frame; +} + +static pui_bool +_ani_clear_fadeout_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; + default_frame_info_t *frame; + unsigned int r = 0x0, g = 0x0, b = 0x0; + + ani_data = pui_backend_ani_get_ani_data(ani); + default_ani_info *ani_info = (default_ani_info *)ani_data->ani_info; + + /* TODO : make use of ani_info */ + //(void) ani_info; + + buffer = pui_backend_ani_get_buffer(ani); + if (!buffer) { + pui_err("Failed to get buffer for animation\n"); + return (pui_bool)0; + } + + frame = _ani_clear_fadeout_get_frame(ani_info); + for(int i = 0; i<12; i++) + { + _ani_backend_clear_fadeout_get_led_rgb(frame, i, &r, &g, &b); + buffer->ptr[4*i] = 0; + buffer->ptr[4*i + 1] = b; /* BLUE */ + buffer->ptr[4*i + 2] = g; /* GREEN */ + buffer->ptr[4*i + 3] = r; /* RED */ + } + backend_util_cleanup_frame(frame); + + 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), (repeat| cur: %d, want: %d)\n", + serial, ani_info->repeat_cur, ani_info->repeat); + + if (ani_info->repeat >= 0 && + ani_info->repeat_cur >= ani_info->repeat) + { + ani_data->ani_func->ani_stop(ani, EINA_FALSE); + } + + return (pui_bool)1; +} + +pui_bool +_ani_clear_frame_set(pui_ani_t *ani) +{ + pui_backend_ani_data *ani_data = NULL; + pui_ani_control_buffer *buffer = NULL; + unsigned int color = 0x0; + int i = 0; + + ani_data = pui_backend_ani_get_ani_data(ani); + default_ani_info *info = (default_ani_info *)ani_data->ani_info; + + buffer = pui_backend_ani_get_last_buffer(ani); + if (!buffer) { + pui_err("Failed to get last buffer\n"); + return (pui_bool)0; + } + + for (i = 0; i < info->frames[0].num_led; i++) + { + color = 0x0; + color += (buffer->ptr[4*i + 3] << 16); /* RED */ + color += (buffer->ptr[4*i + 2] << 8); /* GREEN */ + color += (buffer->ptr[4*i + 1]); /* BLUE */ + + info->frames[0].leds[i].color = color; + } + return (pui_bool)1; +} + +pui_error +_ani_clear_fadeout_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; + + pui_info("... info->id: %s, repeat : %d, interval: %d\n", info->id, repeat, info->interval); + + if (!_ani_clear_frame_set(ani)) + { + pui_err("Failed to set frame for a clear animation\n"); + return PUI_INT_ERROR_INVALID_BUFFER; + } + + pui_backend_ani_status_update(ani, PUI_ANI_STATUS_STARTED); + + info->repeat = 1; + + info->key_frame_cur = 0; + info->frame_idx = 0; + info->repeat_cur = 0; + + if (!ani_frame) + ani_frame = backend_util_alloc_frame(info); + ERROR_CHECK(ani_frame, return PUI_INT_ERROR_INVALID_RESOURCES, "Failed to alloc memory for frame\n"); + + ret = pui_backend_ani_add_frame_cb(ani, _ani_clear_fadeout_frame_cb, info->interval / 1000.0); + if (!ret) + { + pui_err("Failed to add frame callback !\n"); + e = PUI_INT_ERROR_INVALID_RESOURCES; + } + + return e; +} + +pui_error +_ani_clear_fadeout_stop(pui_ani_t *ani, pui_bool force) +{ + 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; + + //TODO + (void) info; + + pui_info("... info->id: %s, force=%d\n", info->id, force); + + pui_backend_ani_remove_frame_cb(ani); + + if (force) + pui_backend_ani_status_update(ani, PUI_ANI_STATUS_PAUSED); + else + pui_backend_ani_status_update(ani, PUI_ANI_STATUS_STOPPED); + + if (ani_frame) + { + backend_util_free_frame(ani_frame); + ani_frame = NULL; + } + + return e; +} + +void +pui_default_backend_ani_clear_fadeout_func_set(pui_backend_ani_func *func) +{ + if (!func) return; + + func->ani_start = _ani_clear_fadeout_start; + func->ani_stop = _ani_clear_fadeout_stop; +} diff --git a/backends/default/default_ani_clear_immediate.c b/backends/default/default_ani_clear_immediate.c new file mode 100644 index 0000000..5a2b0be --- /dev/null +++ b/backends/default/default_ani_clear_immediate.c @@ -0,0 +1,186 @@ +/* + * 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" +static void +_ani_backend_clear_immediate_get_led_rgb(default_frame_info_t *frame, int led_idx, unsigned int *r, unsigned int *g, unsigned int *b) +{ + if (!frame) return; + if (!r || !g || !b) return; + if (led_idx > frame->num_led) return; + + *r = (frame->leds[led_idx].color & LED_MASK_RED) >> 16; + *g = (frame->leds[led_idx].color & LED_MASK_GREEN) >> 8; + *b = (frame->leds[led_idx].color & LED_MASK_BLUE); +} + +static default_frame_info_t *ani_frame = NULL; + +static default_frame_info_t * +_ani_clear_immediate_get_frame(default_ani_info *ani_info) +{ + for (int i = 0; i < ani_frame->num_led; i++) + { + ani_frame->leds[i].color = 0x0; + } + + ani_info->repeat_cur = 1; + + return ani_frame; +} + +static pui_bool +_ani_clear_immediate_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; + default_frame_info_t *frame; + unsigned int r = 0x0, g = 0x0, b = 0x0; + + ani_data = pui_backend_ani_get_ani_data(ani); + default_ani_info *ani_info = (default_ani_info *)ani_data->ani_info; + + /* TODO : make use of ani_info */ + //(void) ani_info; + + buffer = pui_backend_ani_get_buffer(ani); + if (!buffer) { + pui_err("Failed to get buffer for animation\n"); + return (pui_bool)0; + } + + frame = _ani_clear_immediate_get_frame(ani_info); + for(int i = 0; i<12; i++) + { + _ani_backend_clear_immediate_get_led_rgb(frame, i, &r, &g, &b); + buffer->ptr[4*i] = 0; + buffer->ptr[4*i + 1] = b; /* BLUE */ + buffer->ptr[4*i + 2] = g; /* GREEN */ + buffer->ptr[4*i + 3] = r; /* RED */ + } + backend_util_cleanup_frame(frame); + + 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), (repeat| cur: %d, want: %d)\n", + serial, ani_info->repeat_cur, ani_info->repeat); + + if (ani_info->repeat >= 0 && + ani_info->repeat_cur >= ani_info->repeat) + { + ani_data->ani_func->ani_stop(ani, EINA_FALSE); + } + + return (pui_bool)1; +} + +pui_error +_ani_clear_immediate_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; + + pui_info("... info->id: %s, repeat : %d, interval: %d\n", info->id, repeat, info->interval); + + pui_backend_ani_status_update(ani, PUI_ANI_STATUS_STARTED); + + info->repeat = 1; + + info->key_frame_cur = 0; + info->frame_idx = 0; + info->repeat_cur = 0; + + if (!ani_frame) + ani_frame = backend_util_alloc_frame(info); + ERROR_CHECK(ani_frame, return PUI_INT_ERROR_INVALID_RESOURCES, "Failed to alloc memory for frame\n"); + + ret = pui_backend_ani_add_frame_cb(ani, _ani_clear_immediate_frame_cb, info->interval / 1000.0); + if (!ret) + { + pui_err("Failed to add frame callback !\n"); + e = PUI_INT_ERROR_INVALID_RESOURCES; + } + + return e; +} + +pui_error +_ani_clear_immediate_stop(pui_ani_t *ani, pui_bool force) +{ + 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; + + //TODO + (void) info; + + pui_info("... info->id: %s, force=%d\n", info->id, force); + + pui_backend_ani_remove_frame_cb(ani); + + if (force) + pui_backend_ani_status_update(ani, PUI_ANI_STATUS_PAUSED); + else + pui_backend_ani_status_update(ani, PUI_ANI_STATUS_STOPPED); + + if (ani_frame) + { + backend_util_free_frame(ani_frame); + ani_frame = NULL; + } + + return e; +} + +void +pui_default_backend_ani_clear_immediate_func_set(pui_backend_ani_func *func) +{ + if (!func) return; + + func->ani_start = _ani_clear_immediate_start; + func->ani_stop = _ani_clear_immediate_stop; +} diff --git a/backends/default_backend.c b/backends/default_backend.c index 7c7f6c9..789e0f9 100644 --- a/backends/default_backend.c +++ b/backends/default_backend.c @@ -359,6 +359,46 @@ _find_directory(const char *path, Eina_List **json_list) return count; } +default_ani_info * +_create_default_ani_info(char *type) +{ + default_ani_info *ani_info = NULL; + int frame_len = 1; + int led_len = 12; + + ani_info = (default_ani_info *)calloc(1, sizeof(default_ani_info)); + ERROR_CHECK(ani_info, goto error, "Failed to alloc for animation info\n"); + + ani_info->id = strndup(type, strlen(type)); + ani_info->interval = 50; + + 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"); + + ani_info->frames[0].frame_duration = 500; + ani_info->frames[0].num_led = led_len; + ani_info->max_leds = led_len; + ani_info->frames[0].leds = (default_led_info_t *)calloc(sizeof(default_led_info_t), led_len); + ERROR_CHECK(ani_info->frames[0].leds, goto error, "Failed to alloc for default_led_info_t\n"); + + return ani_info; + +error: + if (ani_info) { + if (ani_info->frames) { + for (int 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; +} + pui_int_error _create_ani_collection(void) @@ -373,6 +413,8 @@ _create_ani_collection(void) _find_directory(ANI_COLLECTION_DIR, &json_list); + pui_err("Start create ani collect...\n"); + EINA_LIST_FOREACH_SAFE(json_list, l, l_next, path) { ani_info = _read_json(path); @@ -385,6 +427,18 @@ _create_ani_collection(void) } //TODO + ani_info = _create_default_ani_info("default/clear_fadeout"); + if (ani_info) { + eina_hash_add(_animations_hash, ani_info->id, ani_info); + pui_err("Success to load default animation (id: %s)\n", ani_info->id); + } + ani_info = _create_default_ani_info("default/clear_immediate"); + if (ani_info) { + eina_hash_add(_animations_hash, ani_info->id, ani_info); + pui_err("Success to load default animation (id: %s)\n", ani_info->id); + } + + pui_err("End create ani collect...\n"); return e; } @@ -553,6 +607,14 @@ _ani_create(pui_id id) { pui_default_backend_ani_connected_func_set(ani_func); } + else if (!strncmp(ani_info->id, "default/clear_fadeout", sizeof("default/clear_fadeout"))) + { + pui_default_backend_ani_clear_fadeout_func_set(ani_func); + } + else if (!strncmp(ani_info->id, "default/clear_immediate", sizeof("default/clear_immediate"))) + { + pui_default_backend_ani_clear_immediate_func_set(ani_func); + } else { pui_info("%s animation has no animation handler, using default handler\n", ani_info->id); diff --git a/backends/default_backend.h b/backends/default_backend.h index 62c6786..3755b3d 100644 --- a/backends/default_backend.h +++ b/backends/default_backend.h @@ -123,3 +123,5 @@ void pui_default_backend_ani_error_func_set(pui_backend_ani_func *func); void pui_default_backend_ani_alarm_func_set(pui_backend_ani_func *func); void pui_default_backend_ani_connected_func_set(pui_backend_ani_func *func); void pui_default_backend_ani_pairing_func_set(pui_backend_ani_func *func); +void pui_default_backend_ani_clear_fadeout_func_set(pui_backend_ani_func *func); +void pui_default_backend_ani_clear_immediate_func_set(pui_backend_ani_func *func); diff --git a/include/PUI.h b/include/PUI.h index 38e8aa9..8e96370 100644 --- a/include/PUI.h +++ b/include/PUI.h @@ -84,6 +84,9 @@ PUI_API int pui_ani_get_repeat(pui_ani_h ani_h); PUI_API pui_ani_control_buffer * +pui_display_get_last_buffer(pui_h handle); + +PUI_API pui_ani_control_buffer * pui_display_get_buffer(pui_h handle); PUI_API pui_error diff --git a/include/PUI_backend.h b/include/PUI_backend.h index 6dc84f0..e399fc4 100644 --- a/include/PUI_backend.h +++ b/include/PUI_backend.h @@ -92,6 +92,9 @@ extern "C" { #endif pui_ani_control_buffer * +pui_backend_ani_get_last_buffer(pui_ani_t *ani); + +pui_ani_control_buffer * pui_backend_ani_get_buffer(pui_ani_t *ani); pui_int_error diff --git a/src/PUI.c b/src/PUI.c index 9419394..e75b09a 100644 --- a/src/PUI.c +++ b/src/PUI.c @@ -154,6 +154,31 @@ static const struct wl_buffer_listener buffer_listener = { }; pui_ani_control_buffer * +pui_display_get_last_buffer(pui_h handle) +{ + tbm_surface_error_e ret; + tbm_surface_h surface; + pui_ani_control_buffer *buffer = NULL; + + if (!PUI_MAGIC_CHECK(handle, PUI_MAGIC_PUI_H)) + { + PUI_MAGIC_FAIL(handle, PUI_MAGIC_PUI_H, __FUNCTION__); + return NULL; + } + + if (handle->current_sinfo.size <= 0) + { + pui_err("Failed to get last buffer which is not set\n"); + return buffer; + } + + buffer = (pui_ani_control_buffer *)&(handle->current_sinfo.planes[0].ptr); + + return buffer; +} + + +pui_ani_control_buffer * pui_display_get_buffer(pui_h handle) { tbm_surface_error_e ret; diff --git a/src/PUI_ani.c b/src/PUI_ani.c index 40b0a3e..e42a4cc 100644 --- a/src/PUI_ani.c +++ b/src/PUI_ani.c @@ -73,6 +73,24 @@ _pui_ani_cb_frame_done(Ecore_Wl2_Window *win, uint32_t timestamp EINA_UNUSED, vo } pui_ani_control_buffer * +pui_ani_get_last_buffer(pui_ani_h ani_h) +{ + pui_h handle = NULL; + pui_ani_control_buffer *buffer = NULL; + + if (!PUI_MAGIC_CHECK(ani_h, PUI_MAGIC_ANI_H)) + { + PUI_MAGIC_FAIL(ani_h, PUI_MAGIC_ANI_H, __FUNCTION__); + return NULL; + } + + handle = ani_h->pui_handle; + buffer = pui_display_get_last_buffer(handle); + + return buffer; +} + +pui_ani_control_buffer * pui_ani_get_buffer(pui_ani_h ani_h) { pui_h handle = NULL; diff --git a/src/PUI_backend.c b/src/PUI_backend.c index 371daf4..b3e3cd9 100644 --- a/src/PUI_backend.c +++ b/src/PUI_backend.c @@ -27,6 +27,25 @@ #include "PUI_backend.h" pui_ani_control_buffer * +pui_backend_ani_get_last_buffer(pui_ani_t *ani) +{ + pui_ani_control_buffer *buffer = NULL; + + if (!PUI_MAGIC_CHECK(ani, PUI_MAGIC_ANI_T)) + { + PUI_MAGIC_FAIL(ani, PUI_MAGIC_ANI_T, __FUNCTION__); + return NULL; + } + + buffer = pui_ani_get_last_buffer(ani->ani_h); + + if (!buffer) + return NULL; + + return buffer; +} + +pui_ani_control_buffer * pui_backend_ani_get_buffer(pui_ani_t *ani) { pui_ani_control_buffer *buffer = NULL; diff --git a/src/PUI_internal.h b/src/PUI_internal.h index 39c6af7..cef423b 100644 --- a/src/PUI_internal.h +++ b/src/PUI_internal.h @@ -126,6 +126,9 @@ void _pui_magic_fail(const void *p, PUI_Magic m, PUI_Magic req_m, const char *fname); pui_ani_control_buffer * +pui_ani_get_last_buffer(pui_ani_h ani_h); + +pui_ani_control_buffer * pui_ani_get_buffer(pui_ani_h ani_h); pui_int_error -- 2.7.4