* fix(msg): fill callback prototype lv_msg_subscribe_cb_t does not follow the callback conventions. Remove unused void* argument to fix that. * fix(msg): move subs_ll to gc roots * fix(msg): rename subsribe to subscribe * fix(msg): update docs * fix(msg): Add example_1 * fix(msg): fix include paths * fix(mgs): Fix python example typo and comments * fix(msg): LV_EVENT_MSG_RECEIVED event code
170 lines
3.5 KiB
C
170 lines
3.5 KiB
C
/**
|
|
* @file lv_msg.c
|
|
*
|
|
*/
|
|
|
|
/*********************
|
|
* INCLUDES
|
|
*********************/
|
|
#include "lv_msg.h"
|
|
#if LV_USE_MSG
|
|
|
|
#include "../../misc/lv_assert.h"
|
|
#include "../../misc/lv_ll.h"
|
|
#include "../../misc/lv_gc.h"
|
|
|
|
/*********************
|
|
* DEFINES
|
|
*********************/
|
|
|
|
/**********************
|
|
* TYPEDEFS
|
|
**********************/
|
|
|
|
typedef struct {
|
|
uint32_t msg_id;
|
|
lv_msg_subscribe_cb_t callback;
|
|
void * user_data;
|
|
void * _priv_data; /*Internal: used only store 'obj' in lv_obj_subscribe*/
|
|
} sub_dsc_t;
|
|
|
|
/**********************
|
|
* STATIC PROTOTYPES
|
|
**********************/
|
|
|
|
static void notify(lv_msg_t * m);
|
|
static void obj_notify_cb(lv_msg_t * m);
|
|
static void obj_delete_event_cb(lv_event_t * e);
|
|
|
|
/**********************
|
|
* STATIC VARIABLES
|
|
**********************/
|
|
|
|
/**********************
|
|
* GLOBAL VARIABLES
|
|
**********************/
|
|
|
|
/**********************
|
|
* MACROS
|
|
**********************/
|
|
|
|
/**********************
|
|
* GLOBAL FUNCTIONS
|
|
**********************/
|
|
|
|
void lv_msg_init(void)
|
|
{
|
|
_lv_ll_init(&LV_GC_ROOT(_subs_ll), sizeof(sub_dsc_t));
|
|
}
|
|
|
|
void * lv_msg_subscribe(uint32_t msg_id, lv_msg_subscribe_cb_t cb, void * user_data)
|
|
{
|
|
sub_dsc_t * s = _lv_ll_ins_tail(&LV_GC_ROOT(_subs_ll));
|
|
LV_ASSERT_MALLOC(s);
|
|
if(s == NULL) return NULL;
|
|
|
|
lv_memzero(s, sizeof(*s));
|
|
|
|
s->msg_id = msg_id;
|
|
s->callback = cb;
|
|
s->user_data = user_data;
|
|
return s;
|
|
}
|
|
|
|
void * lv_msg_subscribe_obj(uint32_t msg_id, lv_obj_t * obj, void * user_data)
|
|
{
|
|
sub_dsc_t * s = lv_msg_subscribe(msg_id, obj_notify_cb, user_data);
|
|
if(s == NULL) return NULL;
|
|
s->_priv_data = obj;
|
|
|
|
/*If not added yet, add a delete event cb which automatically unsubcribes the object*/
|
|
sub_dsc_t * s_first = lv_obj_get_event_user_data(obj, obj_delete_event_cb);
|
|
if(s_first == NULL) {
|
|
lv_obj_add_event_cb(obj, obj_delete_event_cb, LV_EVENT_DELETE, s);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
void lv_msg_unsubscribe(void * s)
|
|
{
|
|
LV_ASSERT_NULL(s);
|
|
_lv_ll_remove(&LV_GC_ROOT(_subs_ll), s);
|
|
lv_free(s);
|
|
}
|
|
|
|
void lv_msg_send(uint32_t msg_id, const void * payload)
|
|
{
|
|
lv_msg_t m;
|
|
lv_memzero(&m, sizeof(m));
|
|
m.id = msg_id;
|
|
m.payload = payload;
|
|
notify(&m);
|
|
}
|
|
|
|
uint32_t lv_msg_get_id(lv_msg_t * m)
|
|
{
|
|
return m->id;
|
|
}
|
|
|
|
const void * lv_msg_get_payload(lv_msg_t * m)
|
|
{
|
|
return m->payload;
|
|
}
|
|
|
|
void * lv_msg_get_user_data(lv_msg_t * m)
|
|
{
|
|
return m->user_data;
|
|
}
|
|
|
|
lv_msg_t * lv_event_get_msg(lv_event_t * e)
|
|
{
|
|
if(e->code == LV_EVENT_MSG_RECEIVED) {
|
|
return lv_event_get_param(e);
|
|
}
|
|
else {
|
|
LV_LOG_WARN("Not interpreted with this event code");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**********************
|
|
* STATIC FUNCTIONS
|
|
**********************/
|
|
|
|
static void notify(lv_msg_t * m)
|
|
{
|
|
sub_dsc_t * s;
|
|
_LV_LL_READ(&LV_GC_ROOT(_subs_ll), s) {
|
|
if(s->msg_id == m->id && s->callback) {
|
|
m->user_data = s->user_data;
|
|
m->_priv_data = s->_priv_data;
|
|
s->callback(m);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void obj_notify_cb(lv_msg_t * m)
|
|
{
|
|
lv_event_send(m->_priv_data, LV_EVENT_MSG_RECEIVED, m);
|
|
}
|
|
|
|
static void obj_delete_event_cb(lv_event_t * e)
|
|
{
|
|
lv_obj_t * obj = lv_event_get_target(e);
|
|
|
|
sub_dsc_t * s = _lv_ll_get_head(&LV_GC_ROOT(_subs_ll));
|
|
sub_dsc_t * s_next;
|
|
while(s) {
|
|
/*On unsubscribe the list changes s becomes invalid so get next item while it's surely valid*/
|
|
s_next = _lv_ll_get_next(&LV_GC_ROOT(_subs_ll), s);
|
|
if(s->_priv_data == obj) {
|
|
lv_msg_unsubscribe(s);
|
|
}
|
|
s = s_next;
|
|
}
|
|
}
|
|
|
|
#endif /*LV_USE_MSG*/
|