efl/src/bin/efreet/efreetd_ipc.c

239 lines
5.6 KiB
C

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Ecore.h>
#include <Ecore_Ipc.h>
#include "efreetd.h"
#include "efreetd_cache.h"
static int init = 0;
static Ecore_Ipc_Server *ipc = NULL;
static Ecore_Event_Handler *hnd_add = NULL;
static Ecore_Event_Handler *hnd_del = NULL;
static Ecore_Event_Handler *hnd_data = NULL;
static int clients = 0;
static Ecore_Timer *quit_timer = NULL;
static Eina_Bool
_cb_quit_timer(void *data EINA_UNUSED)
{
quit_timer = NULL;
quit();
return EINA_FALSE;
}
static void
_broadcast(Ecore_Ipc_Server *svr, int major, int minor, void *data, int size)
{
Eina_List *ipc_clients = ecore_ipc_server_clients_get(svr);
Eina_List *l;
Ecore_Ipc_Client *cl;
EINA_LIST_FOREACH(ipc_clients, l, cl)
{
ecore_ipc_client_send(cl, major, minor, 0, 0, 0, data, size);
}
}
static char *
_parse_str(void *data, int size)
{
char *str = malloc(size + 1);
if (!str) return NULL;
memcpy(str, data, size);
str[size] = 0;
return str;
}
static Eina_List *
_parse_strs(void *data, int size)
{
Eina_List *list = NULL;
char *p, *p0 = NULL, *p1 = NULL, *e = (char *)data + size;
for (p = data; p < e; p++)
{
if (!p0)
{
if (*p)
{
p0 = p;
p1 = e;
}
}
if ((!*p) && (p0))
{
p1 = strdup(p0);
if (p1) list = eina_list_append(list, p1);
p0 = NULL;
}
}
if (p0)
{
p = malloc(p1 - p0 + 1);
if (p)
{
memcpy(p, p0, p1 - p0);
p[p1 - p0] = 0;
list = eina_list_append(list, p);
}
}
return list;
}
#define IPC_HEAD(_type) \
Ecore_Ipc_Event_Client_##_type *e = event; \
if (ecore_ipc_client_server_get(e->client) != ipc) \
return ECORE_CALLBACK_PASS_ON
static Eina_Bool
_cb_client_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
IPC_HEAD(Add);
if (quit_timer)
{
ecore_timer_del(quit_timer);
quit_timer = NULL;
}
clients++;
return ECORE_CALLBACK_DONE;
}
static Eina_Bool
_cb_client_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
IPC_HEAD(Del);
clients--;
if (clients == 0)
{
if (quit_timer) ecore_timer_del(quit_timer);
quit_timer = ecore_timer_add(10.0, _cb_quit_timer, NULL);
}
return ECORE_CALLBACK_DONE;
}
static Eina_Bool
_cb_client_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
Eina_List *strs;
char *s;
IPC_HEAD(Data);
if (e->major == 1) // register lang
{ // input: str -> lang
if ((s = _parse_str(e->data, e->size)))
{
setenv("LANG", s, 1);
free(s);
}
// return if desktop cache exists (bool as minor)
ecore_ipc_client_send(e->client, 1 /* register reply */,
cache_desktop_exists(), 0, 0, 0, NULL, 0);
}
else if (e->major == 2) // add desktop dirs
{ // input: array of str -> dirs
strs = _parse_strs(e->data, e->size);
EINA_LIST_FREE(strs, s)
{
cache_desktop_dir_add(s);
free(s);
}
}
else if (e->major == 3) // build desktop cache
{ // input: str -> lang
if ((s = _parse_str(e->data, e->size)))
{
setenv("LANG", s, 1);
free(s);
}
cache_desktop_update();
}
else if (e->major == 4) // add icon dirs
{ // input: array of str -> dirs
strs = _parse_strs(e->data, e->size);
EINA_LIST_FREE(strs, s)
{
cache_icon_dir_add(s);
free(s);
}
}
else if (e->major == 5) // add icon exts
{ // input: array of str -> exts
strs = _parse_strs(e->data, e->size);
EINA_LIST_FREE(strs, s)
{
cache_icon_ext_add(s);
free(s);
}
}
return ECORE_CALLBACK_DONE;
}
///////////////////////////////////////////////////////////////////////////
void
send_signal_icon_cache_update(Eina_Bool update)
{
_broadcast(ipc, 2 /* icon cache update */, update, NULL, 0);
}
void
send_signal_desktop_cache_update(Eina_Bool update)
{
_broadcast(ipc, 3 /* desktop cache update */, update, NULL, 0);
}
void
send_signal_desktop_cache_build(void)
{
_broadcast(ipc, 1 /* desktop cache build */, 1, NULL, 0);
}
void
send_signal_mime_cache_build(void)
{
_broadcast(ipc, 4 /* mime cache build */, 1, NULL, 0);
}
Eina_Bool
ipc_init(void)
{
if (init > 0) return EINA_TRUE;
if (!ecore_ipc_init()) return EINA_FALSE;
ipc = ecore_ipc_server_add(ECORE_IPC_LOCAL_USER, "efreetd", 0, NULL);
if (!ipc)
{
ecore_ipc_shutdown();
return EINA_FALSE;
}
quit_timer = ecore_timer_add(10.0, _cb_quit_timer, NULL);
hnd_add = ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_ADD,
_cb_client_add, NULL);
hnd_del = ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DEL,
_cb_client_del, NULL);
hnd_data = ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DATA,
_cb_client_data, NULL);
init++;
return EINA_TRUE;
}
Eina_Bool
ipc_shutdown(void)
{
if (init <= 0) return EINA_TRUE;
init--;
if (init > 0) return EINA_TRUE;
ecore_ipc_server_del(ipc);
ecore_event_handler_del(hnd_add);
ecore_event_handler_del(hnd_del);
ecore_event_handler_del(hnd_data);
ipc = NULL;
hnd_add = NULL;
hnd_del = NULL;
hnd_data = NULL;
ecore_ipc_shutdown();
return EINA_TRUE;
}