efl/src/bin/ecore_buffer/bq_mgr.c

900 lines
25 KiB
C

#include <signal.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <Eina.h>
#include <Ecore_Getopt.h>
#include <wayland-server.h>
#include "bq_mgr_protocol.h"
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
#define BQ_LOG(f, x...) printf("[ES|%30.30s|%04d] " f "\n", __func__, __LINE__, ##x)
#define BQ_DEBUG(f, x...) if (debug) printf("[ES|%30.30s|%04d] " f "\n", __func__, __LINE__, ##x)
#define BQ_OBJECT_NEW(x, f) bq_object_new(sizeof(x), ((Bq_Object_Free_Func)(f)))
#define BQ_OBJECT(x) ((Bq_Object *)(x))
#define BQ_OBJECT_RESOURCE(x) (((Bq_Object *)(x))->resource)
typedef void (*Bq_Object_Free_Func) (void *obj);
typedef struct _Bq_Object Bq_Object;
typedef struct _Bq_Mgr Bq_Mgr;
typedef struct _Bq_Buffer_Queue Bq_Buffer_Queue;
typedef struct _Bq_Buffer_Consumer Bq_Buffer_Consumer;
typedef struct _Bq_Buffer_Provider Bq_Buffer_Provider;
typedef struct _Bq_Buffer Bq_Buffer;
typedef enum _Bq_Buffer_Type Bq_Buffer_Type;
struct _Bq_Object
{
int ref;
Bq_Object_Free_Func free_fn;
Eina_Bool deleted;
struct wl_resource *resource;
};
struct _Bq_Mgr
{
Bq_Object bq_obj;
struct wl_display *wdpy;
struct wl_event_source *signals[3];
/*BufferQueue manager*/
struct wl_global *bq_mgr;
Eina_Hash *buffer_queues;
};
struct _Bq_Buffer_Queue
{
Bq_Object bq_obj;
Eina_Hash *link;
char *name;
struct wl_signal connect;
Bq_Buffer_Consumer *consumer;
Bq_Buffer_Provider *provider;
Eina_Inlist *buffers;
};
struct _Bq_Buffer_Consumer
{
Bq_Object bq_obj;
Bq_Buffer_Queue *buffer_queue;
int32_t queue_size;
int32_t width;
int32_t height;
};
struct _Bq_Buffer_Provider
{
Bq_Object bq_obj;
Bq_Buffer_Queue *buffer_queue;
};
enum _Bq_Buffer_Type
{
bq_BUFFER_TYPE_ID,
bq_BUFFER_TYPE_FD,
};
struct _Bq_Buffer
{
Bq_Object bq_obj; /*Dont use wl_resource in bq_obj*/
EINA_INLIST;
struct wl_resource *consumer;
struct wl_resource *provider;
uint32_t serial;
char *engine;
Bq_Buffer_Type type;
int32_t width;
int32_t height;
int32_t format;
uint32_t flags;
int32_t id;
int32_t offset0;
int32_t stride0;
int32_t offset1;
int32_t stride1;
int32_t offset2;
int32_t stride2;
};
static Eina_Bool debug;
static void *
bq_object_new(size_t size, Bq_Object_Free_Func fn)
{
Bq_Object *o = calloc(1, size);
if ((!o)) return NULL;
o->ref = 1;
o->free_fn = fn;
return o;
}
static int
bq_object_ref(Bq_Object *o)
{
o->ref++;
return o->ref;
}
static int
bq_object_unref(Bq_Object *o)
{
o->ref--;
if (o->ref <= 0 || o->deleted)
{
if (o->free_fn)
o->free_fn(o);
free(o);
}
return o->ref;
}
static int
bq_object_free(Bq_Object *o)
{
if (!o) return 0;
if (o->deleted) return 0;
o->deleted = EINA_TRUE;
return bq_object_unref(o);
}
static void
bq_mgr_buffer_queue_free(Bq_Buffer_Queue *bq)
{
Bq_Buffer *buf;
if (!bq) return;
BQ_DEBUG("destroy buffer queue : %s\n", bq->name);
if (bq->consumer)
{
wl_resource_destroy(BQ_OBJECT_RESOURCE(bq->consumer));
bq->consumer = NULL;
}
if (bq->provider)
{
wl_resource_destroy(BQ_OBJECT_RESOURCE(bq->provider));
bq->provider = NULL;
}
while (bq->buffers)
{
buf = EINA_INLIST_CONTAINER_GET(bq->buffers,Bq_Buffer);
bq->buffers = eina_inlist_remove(bq->buffers, bq->buffers);
if (buf->consumer)
{
wl_resource_destroy(buf->consumer);
buf->consumer = NULL;
}
if (buf->provider)
{
wl_resource_destroy(buf->provider);
buf->provider = NULL;
}
}
if (bq->link)
{
eina_hash_del(bq->link, bq->name, bq);
bq->link = NULL;
}
if (bq->name)
{
free(bq->name);
bq->name = NULL;
}
}
static Bq_Buffer_Queue*
bq_mgr_buffer_queue_new(Bq_Mgr *bq_mgr, const char *name)
{
Bq_Buffer_Queue *bq;
bq = eina_hash_find(bq_mgr->buffer_queues, name);
if (bq)
{
bq_object_ref(BQ_OBJECT(bq));
return bq;
}
bq = BQ_OBJECT_NEW(Bq_Buffer_Queue, bq_mgr_buffer_queue_free);
EINA_SAFETY_ON_NULL_RETURN_VAL(bq, NULL);
bq->link = bq_mgr->buffer_queues;
bq->name = strdup(name);
if (!eina_hash_add(bq->link,bq->name,bq))
{
bq_object_free(BQ_OBJECT(bq));
return NULL;
}
wl_signal_init(&bq->connect);
bq->buffers = NULL;
return bq;
}
static void
bq_mgr_buffer_consumer_release_buffer(struct wl_client *client EINA_UNUSED,
struct wl_resource *resource,
struct wl_resource *buffer)
{
Bq_Buffer_Queue *bq;
Bq_Buffer_Consumer *bq_consumer;
Bq_Buffer_Provider *bq_provider;
Bq_Buffer *bq_buffer;
bq_consumer = (Bq_Buffer_Consumer*)wl_resource_get_user_data(resource);
bq_buffer = (Bq_Buffer*)wl_resource_get_user_data(buffer);
bq = bq_consumer->buffer_queue;
bq_provider = bq->provider;
if (bq_provider && bq_buffer->provider)
{
bq_provider_send_add_buffer(BQ_OBJECT_RESOURCE(bq_provider),
bq_buffer->provider, bq_buffer->serial);
}
}
static const struct bq_consumer_interface _bq_consumer_interface = {
bq_mgr_buffer_consumer_release_buffer
};
static void
bq_mgr_buffer_consumer_destroy(struct wl_resource *resource)
{
Bq_Buffer_Consumer *bq_consumer = wl_resource_get_user_data(resource);
Bq_Buffer_Provider *bq_provider;
Bq_Buffer_Queue *bq;
Bq_Buffer *buf;
if (!bq_consumer) return;
BQ_DEBUG("destroy buffer consumer : %s\n", bq_consumer->buffer_queue->name);
bq = bq_consumer->buffer_queue;
bq_provider = bq->provider;
bq->consumer = NULL;
BQ_OBJECT_RESOURCE(bq_consumer) = NULL;
if (bq_provider)
{
bq_provider_send_disconnected(BQ_OBJECT_RESOURCE(bq_provider));
}
while (bq->buffers)
{
buf = EINA_INLIST_CONTAINER_GET(bq->buffers,Bq_Buffer);
bq->buffers = eina_inlist_remove(bq->buffers,bq->buffers);
BQ_DEBUG("destroy BUFFER : %d\n", buf->type);
if (buf->consumer)
{
wl_resource_destroy(buf->consumer);
buf->consumer = NULL;
bq_object_unref(BQ_OBJECT(buf));
}
if (buf->provider)
{
wl_resource_destroy(buf->provider);
buf->provider = NULL;
bq_object_unref(BQ_OBJECT(buf));
}
}
bq_object_unref(BQ_OBJECT(bq_consumer));
bq_object_unref(BQ_OBJECT(bq));
}
static void
bq_mgr_buffer_destroy(struct wl_resource *resource)
{
Bq_Buffer *buf = wl_resource_get_user_data(resource);
if (resource == buf->consumer)
{
BQ_DEBUG("destroy buffer : consumer\n");
}
else if (resource == buf->provider)
{
BQ_DEBUG("destroy buffer : provider\n");
}
}
static void
bq_buffer_create_consumer_side(Bq_Buffer_Consumer *bq_consumer, Bq_Buffer *bq_buffer)
{
if (!bq_consumer) return;
bq_buffer->consumer = wl_resource_create(wl_resource_get_client(BQ_OBJECT_RESOURCE(bq_consumer)),
&bq_buffer_interface, 1, 0);
wl_resource_set_implementation(bq_buffer->consumer, NULL, bq_buffer, bq_mgr_buffer_destroy);
bq_object_ref(BQ_OBJECT(bq_buffer));
bq_consumer_send_buffer_attached(BQ_OBJECT_RESOURCE(bq_consumer),
bq_buffer->consumer,
bq_buffer->engine,
bq_buffer->width,
bq_buffer->height,
bq_buffer->format,
bq_buffer->flags);
}
static void
bq_buffer_set_consumer_side(Bq_Buffer_Consumer *bq_consumer, Bq_Buffer *bq_buffer)
{
if (!bq_consumer) return;
EINA_SAFETY_ON_NULL_RETURN(bq_buffer);
EINA_SAFETY_ON_NULL_RETURN(bq_buffer->consumer);
if (bq_buffer->type == bq_BUFFER_TYPE_ID)
bq_consumer_send_set_buffer_id(BQ_OBJECT_RESOURCE(bq_consumer),
bq_buffer->consumer,
bq_buffer->id,
bq_buffer->offset0,
bq_buffer->stride0,
bq_buffer->offset1,
bq_buffer->stride1,
bq_buffer->offset2,
bq_buffer->stride2);
else
{
bq_consumer_send_set_buffer_fd(BQ_OBJECT_RESOURCE(bq_consumer),
bq_buffer->consumer,
bq_buffer->id,
bq_buffer->offset0,
bq_buffer->stride0,
bq_buffer->offset1,
bq_buffer->stride1,
bq_buffer->offset2,
bq_buffer->stride2);
close(bq_buffer->id);
}
}
static void
bq_mgr_buffer_queue_create_consumer(struct wl_client *client,
struct wl_resource *resource,
uint32_t id,
const char *name,
int32_t queue_size,
int32_t width,
int32_t height)
{
Bq_Mgr *bq_mgr = (Bq_Mgr*)wl_resource_get_user_data(resource);
Bq_Buffer_Queue *bq;
Bq_Buffer_Consumer *bq_consumer;
Bq_Buffer_Provider *bq_provider;
Bq_Buffer *buf;
EINA_SAFETY_ON_NULL_RETURN(bq_mgr);
bq = bq_mgr_buffer_queue_new(bq_mgr,name);
EINA_SAFETY_ON_NULL_RETURN(bq);
if (bq->consumer)
{
bq_object_unref(BQ_OBJECT(bq));
wl_resource_post_error(resource,
BQ_MGR_ERROR_ALREADY_USED,
"%s consumer already used",name);
return;
}
bq_consumer = BQ_OBJECT_NEW(Bq_Buffer_Consumer, NULL);
EINA_SAFETY_ON_NULL_RETURN(bq_consumer);
BQ_OBJECT_RESOURCE(bq_consumer) = wl_resource_create(client,
&bq_consumer_interface,
1, id);
if (!BQ_OBJECT_RESOURCE(bq_consumer))
{
bq_object_unref(BQ_OBJECT(bq_consumer));
wl_client_post_no_memory(client);
return;
}
wl_resource_set_implementation(BQ_OBJECT_RESOURCE(bq_consumer),
&_bq_consumer_interface,
bq_consumer,
bq_mgr_buffer_consumer_destroy);
bq_consumer->buffer_queue = bq;
bq_consumer->queue_size = queue_size;
bq_consumer->width = width;
bq_consumer->height = height;
bq_provider = bq->provider;
bq->consumer = bq_consumer;
if (bq_provider)
{
bq_provider_send_connected(BQ_OBJECT_RESOURCE(bq_provider),
queue_size, width, height);
bq_consumer_send_connected(BQ_OBJECT_RESOURCE(bq_consumer));
}
EINA_INLIST_FOREACH(bq->buffers,buf)
{
bq_buffer_create_consumer_side(bq_consumer, buf);
bq_buffer_set_consumer_side(bq_consumer, buf);
}
}
static void
bq_buffer_free(Bq_Buffer *buf)
{
if (buf->engine)
free(buf->engine);
}
static void
bq_mgr_buffer_provider_attatch_buffer(struct wl_client *client,
struct wl_resource *resource,
uint32_t buffer,
const char *engine,
int32_t width,
int32_t height,
int32_t format,
uint32_t flags)
{
Bq_Buffer_Provider *bq_provider = wl_resource_get_user_data(resource);
Bq_Buffer_Consumer *bq_consumer;
Bq_Buffer_Queue *bq;
Bq_Buffer *bq_buffer;
EINA_SAFETY_ON_NULL_RETURN(bq_provider);
bq = bq_provider->buffer_queue;
bq_consumer = bq->consumer;
bq_buffer = BQ_OBJECT_NEW(Bq_Buffer, bq_buffer_free);
bq_buffer->provider = wl_resource_create(client, &bq_buffer_interface, 1, buffer);
wl_resource_set_implementation(bq_buffer->provider, NULL, bq_buffer, bq_mgr_buffer_destroy);
if (!bq_buffer->provider)
{
wl_client_post_no_memory(client);
bq_object_unref(BQ_OBJECT(bq_buffer));
return;
}
bq_buffer->engine = strdup(engine);
bq_buffer->width = width;
bq_buffer->height = height;
bq_buffer->format = format;
bq_buffer->flags = flags;
bq->buffers = eina_inlist_append(bq->buffers,EINA_INLIST_GET(bq_buffer));
BQ_DEBUG("add BUFFER : %d\n", bq_buffer->type);
bq_buffer_create_consumer_side(bq_consumer, bq_buffer);
}
static void
bq_mgr_buffer_provider_set_buffer_id(struct wl_client *client EINA_UNUSED,
struct wl_resource *resource,
struct wl_resource *buffer,
int32_t id,
int32_t offset0,
int32_t stride0,
int32_t offset1,
int32_t stride1,
int32_t offset2,
int32_t stride2)
{
Bq_Buffer_Provider *bq_provider = wl_resource_get_user_data(resource);
Bq_Buffer_Consumer *bq_consumer;
Bq_Buffer_Queue *bq;
Bq_Buffer *bq_buffer;
EINA_SAFETY_ON_NULL_RETURN(bq_provider);
bq = bq_provider->buffer_queue;
bq_consumer = bq->consumer;
bq_buffer = wl_resource_get_user_data(buffer);
EINA_SAFETY_ON_NULL_RETURN(bq_buffer);
bq_buffer->type = bq_BUFFER_TYPE_ID;
bq_buffer->id = id;
bq_buffer->offset0 = offset0;
bq_buffer->stride0 = stride0;
bq_buffer->offset1 = offset1;
bq_buffer->stride1 = stride1;
bq_buffer->offset2 = offset2;
bq_buffer->stride2 = stride2;
bq_buffer_set_consumer_side(bq_consumer, bq_buffer);
}
static void
bq_mgr_buffer_provider_set_buffer_fd(struct wl_client *client EINA_UNUSED,
struct wl_resource *resource,
struct wl_resource *buffer,
int32_t fd,
int32_t offset0,
int32_t stride0,
int32_t offset1,
int32_t stride1,
int32_t offset2,
int32_t stride2)
{
Bq_Buffer_Provider *bq_provider = wl_resource_get_user_data(resource);
Bq_Buffer_Consumer *bq_consumer;
Bq_Buffer_Queue *bq;
Bq_Buffer *bq_buffer;
EINA_SAFETY_ON_NULL_RETURN(bq_provider);
bq = bq_provider->buffer_queue;
bq_consumer = bq->consumer;
bq_buffer = wl_resource_get_user_data(buffer);
EINA_SAFETY_ON_NULL_RETURN(bq_buffer);
bq_buffer->type = bq_BUFFER_TYPE_FD;
bq_buffer->id = fd;
bq_buffer->offset0 = offset0;
bq_buffer->stride0 = stride0;
bq_buffer->offset1 = offset1;
bq_buffer->stride1 = stride1;
bq_buffer->offset2 = offset2;
bq_buffer->stride2 = stride2;
bq_buffer_set_consumer_side(bq_consumer, bq_buffer);
}
static void
bq_mgr_buffer_provider_detach_buffer(struct wl_client *client EINA_UNUSED,
struct wl_resource *resource,
struct wl_resource *buffer)
{
Bq_Buffer_Provider *bq_provider = wl_resource_get_user_data(resource);
Bq_Buffer_Consumer *bq_consumer;
Bq_Buffer_Queue *bq;
Bq_Buffer *bq_buffer;
EINA_SAFETY_ON_NULL_RETURN(bq_provider);
bq = bq_provider->buffer_queue;
bq_consumer = bq->consumer;
bq_buffer = wl_resource_get_user_data(buffer);
if (bq_consumer)
{
bq_consumer_send_buffer_detached(BQ_OBJECT_RESOURCE(bq_consumer),
bq_buffer->consumer);
wl_resource_destroy(bq_buffer->consumer);
bq_object_unref(BQ_OBJECT(bq_buffer));
}
wl_resource_destroy(bq_buffer->provider);
bq->buffers = eina_inlist_remove(bq->buffers,EINA_INLIST_GET(bq_buffer));
bq_object_unref(BQ_OBJECT(bq_buffer));
}
static void
bq_mgr_buffer_provider_enqueue_buffer(struct wl_client *client EINA_UNUSED,
struct wl_resource *resource,
struct wl_resource *buffer,
uint32_t serial)
{
Bq_Buffer_Provider *bq_provider = wl_resource_get_user_data(resource);
Bq_Buffer_Consumer *bq_consumer;
Bq_Buffer_Queue *bq;
Bq_Buffer *bq_buffer;
EINA_SAFETY_ON_NULL_RETURN(bq_provider);
bq = bq_provider->buffer_queue;
bq_consumer = bq->consumer;
if (!bq_consumer)
{
wl_resource_post_error(BQ_OBJECT_RESOURCE(bq_consumer),
BQ_PROVIDER_ERROR_CONNECTION,
"Not connected:%s", bq->name);
return;
}
bq_buffer = wl_resource_get_user_data(buffer);
EINA_SAFETY_ON_NULL_RETURN(bq_buffer);
bq_buffer->serial = serial;
bq_consumer_send_add_buffer(BQ_OBJECT_RESOURCE(bq_consumer),
bq_buffer->consumer,
bq_buffer->serial);
}
static const struct bq_provider_interface _bq_provider_interface = {
bq_mgr_buffer_provider_attatch_buffer,
bq_mgr_buffer_provider_set_buffer_id,
bq_mgr_buffer_provider_set_buffer_fd,
bq_mgr_buffer_provider_detach_buffer,
bq_mgr_buffer_provider_enqueue_buffer
};
static void
bq_mgr_buffer_provider_destroy(struct wl_resource *resource)
{
Bq_Buffer_Queue *bq;
Bq_Buffer_Provider *bq_provider = wl_resource_get_user_data(resource);
Bq_Buffer_Consumer *bq_consumer;
Bq_Buffer *buf;
EINA_SAFETY_ON_NULL_RETURN(bq_provider);
BQ_DEBUG("destroy buffer provider : %s\n", bq_provider->buffer_queue->name);
bq = bq_provider->buffer_queue;
bq_consumer = bq->consumer;
BQ_OBJECT_RESOURCE(bq_provider) = NULL;
bq->provider = NULL;
while (bq->buffers)
{
buf = EINA_INLIST_CONTAINER_GET(bq->buffers, Bq_Buffer);
bq->buffers = eina_inlist_remove(bq->buffers, bq->buffers);
if (buf->consumer)
{
bq_consumer_send_buffer_detached(BQ_OBJECT_RESOURCE(bq_consumer), buf->consumer);
wl_resource_destroy(buf->consumer);
buf->consumer = NULL;
bq_object_unref(BQ_OBJECT(buf));
}
if (buf->provider)
{
wl_resource_destroy(buf->provider);
buf->provider = NULL;
bq_object_unref(BQ_OBJECT(buf));
}
}
if (bq_consumer)
{
if (BQ_OBJECT_RESOURCE(bq_consumer))
bq_consumer_send_disconnected(BQ_OBJECT_RESOURCE(bq_consumer));
}
bq_object_unref(BQ_OBJECT(bq_provider));
bq_object_unref(BQ_OBJECT(bq));
}
static void
bq_mgr_buffer_queue_create_provider(struct wl_client *client,
struct wl_resource *resource,
uint32_t id,
const char *name)
{
Bq_Mgr *bq_mgr = (Bq_Mgr*)wl_resource_get_user_data(resource);
Bq_Buffer_Queue *bq;
Bq_Buffer_Provider *bq_provider;
Bq_Buffer_Consumer *bq_consumer;
EINA_SAFETY_ON_NULL_RETURN(bq_mgr);
bq = bq_mgr_buffer_queue_new(bq_mgr,name);
EINA_SAFETY_ON_NULL_RETURN(bq);
if (bq->provider)
{
bq_object_unref(BQ_OBJECT(bq));
wl_resource_post_error(resource,
BQ_MGR_ERROR_ALREADY_USED,
"%s rpovider already used",name);
return;
}
bq_provider = BQ_OBJECT_NEW(Bq_Buffer_Provider, NULL);
EINA_SAFETY_ON_NULL_GOTO(bq_provider, on_error);
BQ_OBJECT_RESOURCE(bq_provider)= wl_resource_create(client,
&bq_provider_interface,
1, id);
EINA_SAFETY_ON_NULL_GOTO(BQ_OBJECT_RESOURCE(bq_provider), on_error);
wl_resource_set_implementation(BQ_OBJECT_RESOURCE(bq_provider),
&_bq_provider_interface,
bq_provider,
bq_mgr_buffer_provider_destroy);
bq_provider->buffer_queue = bq;
bq->provider = bq_provider;
bq_consumer = bq->consumer;
if (bq_consumer)
{
/*Send connect*/
bq_consumer_send_connected(BQ_OBJECT_RESOURCE(bq_consumer));
bq_provider_send_connected(BQ_OBJECT_RESOURCE(bq_provider),
bq_consumer->queue_size,
bq_consumer->width, bq_consumer->height);
}
return;
on_error:
if (bq) bq_object_unref(BQ_OBJECT(bq));
if (bq_provider) bq_object_unref(BQ_OBJECT(bq_provider));
wl_client_post_no_memory(client);
}
static const struct bq_mgr_interface _bq_mgr_interface =
{
bq_mgr_buffer_queue_create_consumer,
bq_mgr_buffer_queue_create_provider
};
static void
bq_mgr_buffer_queue_bind(struct wl_client *client, void *data,
uint32_t version EINA_UNUSED, uint32_t id)
{
Bq_Mgr *bq_mgr = (Bq_Mgr*)data;
struct wl_resource *resource;
resource = wl_resource_create(client, &bq_mgr_interface,
1, id);
if (resource == NULL) {
wl_client_post_no_memory(client);
return;
}
wl_resource_set_implementation(resource,
&_bq_mgr_interface,
bq_mgr, NULL);
}
Eina_Bool
bq_mgr_buffer_queue_manager_init(Bq_Mgr *bq_mgr)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(bq_mgr,EINA_FALSE);
bq_mgr->bq_mgr = wl_global_create(bq_mgr->wdpy
,&bq_mgr_interface,1
,bq_mgr
,bq_mgr_buffer_queue_bind);
EINA_SAFETY_ON_NULL_RETURN_VAL(bq_mgr->bq_mgr,EINA_FALSE);
bq_mgr->buffer_queues = eina_hash_string_superfast_new(NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(bq_mgr->buffer_queues,EINA_FALSE);
return EINA_TRUE;
}
static const Ecore_Getopt optdesc =
{
"tbm_daemon",
"%prog [options]",
"0.1.0",
"(C) Samsung",
"BSD 2-Clause",
"Tizen Buffer Manager Daemon",
EINA_FALSE,
{
ECORE_GETOPT_STORE_STR('s', "socket_name",
"socket name"),
ECORE_GETOPT_STORE_BOOL('d',"debug","enable debug log"),
ECORE_GETOPT_VERSION('v', "version"),
ECORE_GETOPT_HELP('h', "help"),
ECORE_GETOPT_SENTINEL
}
};
static int
bq_mgr_on_term_signal(int signal_number, void *data)
{
Bq_Mgr *bq_mgr = data;
BQ_LOG("caught signal %d\n", signal_number);
wl_display_terminate(bq_mgr->wdpy);
return 1;
}
static void
bq_mgr_free(Bq_Mgr *bq_mgr)
{
int i;
for (i = ARRAY_LENGTH(bq_mgr->signals) - 1; i >= 0; i--)
{
if (bq_mgr->signals[i])
wl_event_source_remove(bq_mgr->signals[i]);
}
if (bq_mgr->wdpy)
wl_display_destroy(bq_mgr->wdpy);
}
static Bq_Mgr*
bq_mgr_new(char *sock_name)
{
static char *default_sock_name = "bq_mgr_daemon";
Bq_Mgr *bq_mgr = BQ_OBJECT_NEW(Bq_Mgr, bq_mgr_free);
struct wl_event_loop *loop;
if (!bq_mgr) return NULL;
bq_mgr->wdpy = wl_display_create();
loop = wl_display_get_event_loop(bq_mgr->wdpy);
EINA_SAFETY_ON_NULL_GOTO(loop, on_err);
bq_mgr->signals[0] = wl_event_loop_add_signal(loop, SIGTERM, bq_mgr_on_term_signal, bq_mgr);
bq_mgr->signals[1] = wl_event_loop_add_signal(loop, SIGINT, bq_mgr_on_term_signal, bq_mgr);
bq_mgr->signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, bq_mgr_on_term_signal, bq_mgr);
if (!sock_name)
sock_name = default_sock_name;
wl_display_add_socket(bq_mgr->wdpy, sock_name);
return bq_mgr;
on_err:
bq_object_free(BQ_OBJECT(bq_mgr));
return NULL;
}
int
main(int argc, char **argv)
{
Bq_Mgr *bq_mgr = NULL;
int res, ret = EXIT_FAILURE;
char *opt_path = NULL;
Eina_Bool quit = EINA_FALSE;
Ecore_Getopt_Value values[] =
{
ECORE_GETOPT_VALUE_STR(opt_path),
ECORE_GETOPT_VALUE_BOOL(debug),
ECORE_GETOPT_VALUE_BOOL(quit),
ECORE_GETOPT_VALUE_BOOL(quit),
ECORE_GETOPT_VALUE_NONE
};
eina_init();
res = ecore_getopt_parse(&optdesc,
values,
argc, argv);
if ((res < 0) || (quit)) goto finish;
if (opt_path)
BQ_LOG("socket_name : %s\n", opt_path);
bq_mgr = bq_mgr_new(opt_path);
if (!bq_mgr) goto finish;
if (!bq_mgr_buffer_queue_manager_init(bq_mgr))
{
bq_mgr_free(bq_mgr);
goto finish;
}
wl_display_run(bq_mgr->wdpy);
ret = EXIT_SUCCESS;
finish:
eina_shutdown();
bq_object_free(BQ_OBJECT(bq_mgr));
return ret;
}