Files
lvgl/src/others/msg/lv_msg.c
Amir Gonnen cd11476592 fix(msg): make it work with Micropython (#3488)
* 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
2022-07-27 09:42:48 +02:00

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*/