efl/src/bin/ethumb/ethumbd.c

1804 lines
44 KiB
C

/**
* @file
*
* Copyright (C) 2009 by ProFUSION embedded systems
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*
* @author Rafael Antognolli <antognolli@profusion.mobi>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <errno.h>
#include <Eina.h>
#include <Ecore_Getopt.h>
#include <Ecore.h>
#include <EDBus.h>
#include <Ethumb.h>
#include "ethumbd_private.h"
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#define MAX_ID 2000000
#define DAEMON "daemon"
#define ODATA "odata"
#define DBG(...) EINA_LOG_DOM_DBG(_log_domain, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(_log_domain, __VA_ARGS__)
#define WRN(...) EINA_LOG_DOM_WARN(_log_domain, __VA_ARGS__)
#define ERR(...) EINA_LOG_DOM_ERR(_log_domain, __VA_ARGS__)
#define CRIT(...) EINA_LOG_DOM_CRIT(_log_domain, __VA_ARGS__)
static const char _ethumb_dbus_bus_name[] = "org.enlightenment.Ethumb";
static const char _ethumb_dbus_interface[] = "org.enlightenment.Ethumb";
static const char _ethumb_dbus_objects_interface[] = "org.enlightenment.Ethumb.objects";
static const char _ethumb_dbus_path[] = "/org/enlightenment/Ethumb";
static Eina_Prefix *_pfx = NULL;
static int _log_domain = -1;
typedef struct _Ethumbd_Setup Ethumbd_Setup;
typedef struct _Ethumbd_Slave Ethumbd_Slave;
typedef struct _Ethumbd_Request Ethumbd_Request;
typedef struct _Ethumbd_Queue Ethumbd_Queue;
typedef struct _Ethumbd_Object Ethumbd_Object;
typedef struct _Ethumbd_Object_Data Ethumbd_Object_Data;
typedef struct _Ethumbd Ethumbd;
struct _Ethumbd_Setup
{
struct
{
Eina_Bool fdo : 1;
Eina_Bool size : 1;
Eina_Bool format : 1;
Eina_Bool aspect : 1;
Eina_Bool orientation: 1;
Eina_Bool crop : 1;
Eina_Bool quality : 1;
Eina_Bool compress : 1;
Eina_Bool directory : 1;
Eina_Bool category : 1;
Eina_Bool frame : 1;
Eina_Bool video_time : 1;
Eina_Bool video_start : 1;
Eina_Bool video_interval : 1;
Eina_Bool video_ntimes : 1;
Eina_Bool video_fps : 1;
Eina_Bool document_page : 1;
} flags;
int fdo;
int tw, th;
int format;
int aspect;
int orientation;
float cx, cy;
int quality;
int compress;
const char *directory;
const char *category;
const char *theme_file;
const char *group;
const char *swallow;
float video_time;
float video_start;
float video_interval;
unsigned int video_ntimes;
unsigned int video_fps;
unsigned int document_page;
};
struct _Ethumbd_Request
{
int id;
const char *file, *key;
const char *thumb, *thumb_key;
Ethumbd_Setup setup;
};
struct _Ethumbd_Object
{
int used;
const char *path;
const char *client;
Eina_List *queue;
int nqueue;
int id_count;
int max_id;
int min_id;
EDBus_Service_Interface *iface;
};
struct _Ethumbd_Queue
{
int count;
int max_count;
int nqueue;
int last;
int current;
Ethumbd_Object *table;
int *list;
};
struct _Ethumbd_Slave
{
Ecore_Exe *exe;
char *bufcmd; // buffer to read commands from slave
int scmd; // size of command to read
int pcmd; // position in the command buffer
};
struct _Ethumbd
{
EDBus_Connection *conn;
Ecore_Idler *idler;
Ethumbd_Request *processing;
Ethumbd_Queue queue;
double timeout;
Ecore_Timer *timeout_timer;
Ethumbd_Slave slave;
Ecore_Event_Handler *data_cb;
Ecore_Event_Handler *del_cb;
};
struct _Ethumbd_Object_Data
{
int idx;
Ethumbd *ed;
};
const Ecore_Getopt optdesc = {
"ethumbd",
NULL,
PACKAGE_VERSION,
"(C) 2009 - ProFUSION embedded systems",
"LGPL v2.1 - GNU Lesser General Public License",
"Ethumb daemon.\n"
"\n"
"ethumbd uses the Ethumb library to create thumbnails for any "
"program that requests it (now just by dbus).\n",
0,
{
ECORE_GETOPT_STORE_DOUBLE
('t', "timeout", "finish ethumbd after <timeout> seconds of no activity."),
ECORE_GETOPT_LICENSE('L', "license"),
ECORE_GETOPT_COPYRIGHT('C', "copyright"),
ECORE_GETOPT_VERSION('V', "version"),
ECORE_GETOPT_HELP('h', "help"),
ECORE_GETOPT_SENTINEL
}
};
static EDBus_Message *_ethumb_dbus_queue_add_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg);
static EDBus_Message *_ethumb_dbus_queue_remove_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg);
static EDBus_Message *_ethumb_dbus_queue_clear_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg);
static EDBus_Message *_ethumb_dbus_ethumb_setup_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg);
static EDBus_Message *_ethumb_dbus_delete_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg);
static const EDBus_Method _ethumb_dbus_objects_methods[] = {
{
"queue_add",
EDBUS_ARGS({"i", "id"}, {"ay", "file"}, {"ay", "key"}, {"ay", "thumb"}, {"ay", "thumb_key"}),
EDBUS_ARGS({"i", "queue_id"}), _ethumb_dbus_queue_add_cb, 0
},
{
"queue_remove", EDBUS_ARGS({"i", "queue_id"}), EDBUS_ARGS({"b", "result"}),
_ethumb_dbus_queue_remove_cb, 0
},
{
"clear_queue", NULL, NULL, _ethumb_dbus_queue_clear_cb, 0
},
{
"ethumb_setup", EDBUS_ARGS({"a{sv}", "array"}), EDBUS_ARGS({"b", "result"}),
_ethumb_dbus_ethumb_setup_cb, 0
},
{
"delete", NULL, NULL, _ethumb_dbus_delete_cb, 0
},
{ }
};
enum
{
ETHUMB_DBUS_OBJECTS_SIGNAL_GENERATED = 0,
};
static const EDBus_Signal _ethumb_dbus_objects_signals[] = {
[ETHUMB_DBUS_OBJECTS_SIGNAL_GENERATED] = { "generated",
EDBUS_ARGS({ "i", "id" }, { "ay", "paths" }, { "ay", "keys" },
{ "b", "success" }) },
{ }
};
static void _ethumb_dbus_generated_signal(Ethumbd *ed, int *id, const char *thumb_path, const char *thumb_key, Eina_Bool success);
static Eina_Bool _ethumbd_slave_spawn(Ethumbd_Slave *slave, Ethumbd *ed);
static Eina_Bool
_ethumbd_timeout_cb(void *data)
{
Ethumbd *ed = data;
ecore_main_loop_quit();
ed->timeout_timer = NULL;
return 0;
}
static void
_ethumbd_timeout_start(Ethumbd *ed)
{
if (ed->timeout < 0)
return;
if (!ed->timeout_timer)
ed->timeout_timer = ecore_timer_add(ed->timeout, _ethumbd_timeout_cb, ed);
}
static void
_ethumbd_timeout_stop(Ethumbd *ed)
{
if (!ed->timeout_timer)
return;
ecore_timer_del(ed->timeout_timer);
ed->timeout_timer = NULL;
}
static int
_ethumb_dbus_check_id(Ethumbd_Object *eobject, int id)
{
if (id < 0 || id > MAX_ID)
return 0;
if (eobject->min_id < eobject->max_id)
return id < eobject->min_id || id > eobject->max_id;
else if (eobject->min_id > eobject->max_id)
return id < eobject->min_id && id > eobject->max_id;
else
return id != eobject->max_id;
}
static void
_ethumb_dbus_inc_max_id(Ethumbd_Object *eobject, int id)
{
if (eobject->min_id < 0 && eobject->max_id < 0)
eobject->min_id = id;
eobject->max_id = id;
}
static void
_ethumb_dbus_inc_min_id(Ethumbd_Object *eobject)
{
Eina_List *l;
l = eobject->queue;
while (l)
{
Ethumbd_Request *request = l->data;
if (request->id >= 0)
{
eobject->min_id = request->id;
break;
}
l = l->next;
}
if (!l)
{
eobject->min_id = -1;
eobject->max_id = -1;
}
}
int
_ethumbd_write_safe(Ethumbd_Slave *slave, const void *buf, ssize_t size)
{
if (!slave->exe)
{
ERR("slave process isn't running.");
return 0;
}
ecore_exe_send(slave->exe, buf, size);
return 1;
}
static void
_ethumbd_child_write_op_new(Ethumbd_Slave *slave, int idx)
{
int id = ETHUMBD_OP_NEW;
_ethumbd_write_safe(slave, &id, sizeof(id));
_ethumbd_write_safe(slave, &idx, sizeof(idx));
}
static void
_ethumbd_child_write_op_del(Ethumbd_Slave *slave, int idx)
{
int id = ETHUMBD_OP_DEL;
_ethumbd_write_safe(slave, &id, sizeof(id));
_ethumbd_write_safe(slave, &idx, sizeof(idx));
}
static void
_ethumbd_pipe_str_write(Ethumbd_Slave *slave, const char *str)
{
int len;
if (str)
len = strlen(str) + 1;
else
len = 0;
_ethumbd_write_safe(slave, &len, sizeof(len));
_ethumbd_write_safe(slave, str, len);
}
static void
_ethumbd_child_write_op_generate(Ethumbd_Slave *slave,
int idx, const char *path, const char *key,
const char *thumb_path, const char *thumb_key)
{
int id = ETHUMBD_OP_GENERATE;
_ethumbd_write_safe(slave, &id, sizeof(id));
_ethumbd_write_safe(slave, &idx, sizeof(idx));
_ethumbd_pipe_str_write(slave, path);
_ethumbd_pipe_str_write(slave, key);
_ethumbd_pipe_str_write(slave, thumb_path);
_ethumbd_pipe_str_write(slave, thumb_key);
}
static void
_generated_cb(Ethumbd *ed, Eina_Bool success, const char *thumb_path, const char *thumb_key)
{
int i = ed->queue.current;
DBG("thumbnail ready at: \"%s:%s\"", thumb_path, thumb_key);
if (ed->queue.table[i].used)
_ethumb_dbus_generated_signal
(ed, &ed->processing->id, thumb_path, thumb_key, success);
eina_stringshare_del(ed->processing->file);
eina_stringshare_del(ed->processing->key);
eina_stringshare_del(ed->processing->thumb);
eina_stringshare_del(ed->processing->thumb_key);
free(ed->processing);
ed->processing = NULL;
}
static void
_ethumbd_slave_cmd_ready(Ethumbd *ed)
{
const char *bufcmd = ed->slave.bufcmd;
Eina_Bool success;
const char *thumb_path = NULL;
const char *thumb_key = NULL;
int size_path, size_key;
/* NOTE: accessing values directly on bufcmd breaks alignment
* as the first item is an Eina_Bool (size 1) and second is
* an integer (size 4, alignment 4).
* Thus copy to stack values before using them, to have proper alignment.
*/
#define READVAL(dst) \
memcpy(&dst, bufcmd, sizeof(dst)); \
bufcmd += sizeof(dst);
READVAL(success);
READVAL(size_path);
if (size_path)
{
thumb_path = bufcmd;
bufcmd += size_path;
}
READVAL(size_key);
if (size_key) thumb_key = bufcmd;
#undef READVAL
_generated_cb(ed, success, thumb_path, thumb_key);
free(ed->slave.bufcmd);
ed->slave.bufcmd = NULL;
ed->slave.scmd = 0;
}
static int
_ethumbd_slave_alloc_cmd(Ethumbd *ed, int ssize, char *sdata)
{
int *scmd;
if (ed->slave.bufcmd)
return 0;
scmd = (int *)sdata;
if (ssize < (int)sizeof(*scmd)) {
ERR("could not read size of command.");
return 0;
}
ed->slave.bufcmd = malloc(*scmd);
ed->slave.scmd = *scmd;
ed->slave.pcmd = 0;
return sizeof(*scmd);
}
static Eina_Bool
_ethumbd_slave_data_read_cb(void *data, int type EINA_UNUSED, void *event)
{
Ethumbd *ed = data;
Ecore_Exe_Event_Data *ev = event;
int ssize;
char *sdata;
if (ev->exe != ed->slave.exe)
{
ERR("PARENT ERROR: slave != ev->exe");
return 0;
}
ssize = ev->size;
sdata = ev->data;
while (ssize > 0)
{
if (!ed->slave.bufcmd)
{
int n;
n = _ethumbd_slave_alloc_cmd(ed, ssize, sdata);
ssize -= n;
sdata += n;
}
else
{
char *bdata;
int nbytes;
bdata = ed->slave.bufcmd + ed->slave.pcmd;
nbytes = ed->slave.scmd - ed->slave.pcmd;
nbytes = ssize < nbytes ? ssize : nbytes;
memcpy(bdata, sdata, nbytes);
sdata += nbytes;
ssize -= nbytes;
ed->slave.pcmd += nbytes;
if (ed->slave.pcmd == ed->slave.scmd)
_ethumbd_slave_cmd_ready(ed);
}
}
return 1;
}
static Eina_Bool
_ethumbd_slave_del_cb(void *data, int type EINA_UNUSED, void *event)
{
Ethumbd *ed = data;
Ecore_Exe_Event_Del *ev = event;
int i;
if (ev->exe != ed->slave.exe)
return 1;
if (ev->exited)
ERR("slave exited with code: %d", ev->exit_code);
else if (ev->signalled)
ERR("slave exited by signal: %d", ev->exit_signal);
if (!ed->processing)
goto end;
i = ed->queue.current;
ERR("failed to generate thumbnail for: \"%s:%s\"",
ed->processing->file, ed->processing->key);
if (ed->queue.table[i].used)
_ethumb_dbus_generated_signal
(ed, &ed->processing->id, NULL, NULL, EINA_FALSE);
eina_stringshare_del(ed->processing->file);
eina_stringshare_del(ed->processing->key);
eina_stringshare_del(ed->processing->thumb);
eina_stringshare_del(ed->processing->thumb_key);
free(ed->processing);
ed->processing = NULL;
end:
ed->slave.exe = NULL;
if (ed->slave.bufcmd)
free(ed->slave.bufcmd);
if (!_ethumbd_slave_spawn(&ed->slave, ed))
return EINA_FALSE;
/* restart all queue */
for (i = 0; i < ed->queue.count; ++i)
_ethumbd_child_write_op_new(&ed->slave, ed->queue.list[i]);
return EINA_TRUE;
}
static void
_ethumbd_pipe_write_setup(Ethumbd_Slave *slave, int type, const void *data)
{
const int *i_value;
const float *f_value;
_ethumbd_write_safe(slave, &type, sizeof(type));
switch (type)
{
case ETHUMBD_FDO:
case ETHUMBD_FORMAT:
case ETHUMBD_ASPECT:
case ETHUMBD_ORIENTATION:
case ETHUMBD_QUALITY:
case ETHUMBD_COMPRESS:
case ETHUMBD_SIZE_W:
case ETHUMBD_SIZE_H:
case ETHUMBD_DOCUMENT_PAGE:
case ETHUMBD_VIDEO_NTIMES:
case ETHUMBD_VIDEO_FPS:
i_value = data;
_ethumbd_write_safe(slave, i_value, sizeof(*i_value));
break;
case ETHUMBD_CROP_X:
case ETHUMBD_CROP_Y:
case ETHUMBD_VIDEO_TIME:
case ETHUMBD_VIDEO_START:
case ETHUMBD_VIDEO_INTERVAL:
f_value = data;
_ethumbd_write_safe(slave, f_value, sizeof(*f_value));
break;
case ETHUMBD_DIRECTORY:
case ETHUMBD_CATEGORY:
case ETHUMBD_FRAME_FILE:
case ETHUMBD_FRAME_GROUP:
case ETHUMBD_FRAME_SWALLOW:
_ethumbd_pipe_str_write(slave, data);
break;
case ETHUMBD_SETUP_FINISHED:
break;
default:
ERR("wrong ethumb setup parameter.");
}
}
static void
_process_setup(Ethumbd *ed)
{
int op_id = ETHUMBD_OP_SETUP;
int idx = ed->queue.current;
Ethumbd_Setup *setup = &ed->processing->setup;
Ethumbd_Slave *slave = &ed->slave;
_ethumbd_write_safe(slave, &op_id, sizeof(op_id));
_ethumbd_write_safe(slave, &idx, sizeof(idx));
if (setup->flags.fdo)
_ethumbd_pipe_write_setup(slave, ETHUMBD_FDO, &setup->fdo);
if (setup->flags.size)
{
_ethumbd_pipe_write_setup(slave, ETHUMBD_SIZE_W, &setup->tw);
_ethumbd_pipe_write_setup(slave, ETHUMBD_SIZE_H, &setup->th);
}
if (setup->flags.format)
_ethumbd_pipe_write_setup(slave, ETHUMBD_FORMAT, &setup->format);
if (setup->flags.aspect)
_ethumbd_pipe_write_setup(slave, ETHUMBD_ASPECT, &setup->aspect);
if (setup->flags.orientation)
_ethumbd_pipe_write_setup(slave, ETHUMBD_ORIENTATION, &setup->orientation);
if (setup->flags.crop)
{
_ethumbd_pipe_write_setup(slave, ETHUMBD_CROP_X, &setup->cx);
_ethumbd_pipe_write_setup(slave, ETHUMBD_CROP_Y, &setup->cy);
}
if (setup->flags.quality)
_ethumbd_pipe_write_setup(slave, ETHUMBD_QUALITY, &setup->quality);
if (setup->flags.compress)
_ethumbd_pipe_write_setup(slave, ETHUMBD_COMPRESS, &setup->compress);
if (setup->flags.directory)
_ethumbd_pipe_write_setup(slave, ETHUMBD_DIRECTORY, setup->directory);
if (setup->flags.category)
_ethumbd_pipe_write_setup(slave, ETHUMBD_CATEGORY, setup->category);
if (setup->flags.frame)
{
_ethumbd_pipe_write_setup(slave, ETHUMBD_FRAME_FILE, setup->theme_file);
_ethumbd_pipe_write_setup(slave, ETHUMBD_FRAME_GROUP, setup->group);
_ethumbd_pipe_write_setup(slave, ETHUMBD_FRAME_SWALLOW, setup->swallow);
}
if (setup->flags.video_time)
_ethumbd_pipe_write_setup(slave, ETHUMBD_VIDEO_TIME, &setup->video_time);
if (setup->flags.video_start)
_ethumbd_pipe_write_setup(slave, ETHUMBD_VIDEO_START, &setup->video_start);
if (setup->flags.video_interval)
_ethumbd_pipe_write_setup(slave, ETHUMBD_VIDEO_INTERVAL,
&setup->video_interval);
if (setup->flags.video_ntimes)
_ethumbd_pipe_write_setup(slave, ETHUMBD_VIDEO_NTIMES, &setup->video_ntimes);
if (setup->flags.video_fps)
_ethumbd_pipe_write_setup(slave, ETHUMBD_VIDEO_FPS, &setup->video_fps);
if (setup->flags.document_page)
_ethumbd_pipe_write_setup(slave, ETHUMBD_DOCUMENT_PAGE,
&setup->document_page);
_ethumbd_pipe_write_setup(slave, ETHUMBD_SETUP_FINISHED, NULL);
if (setup->directory) eina_stringshare_del(setup->directory);
if (setup->category) eina_stringshare_del(setup->category);
if (setup->theme_file) eina_stringshare_del(setup->theme_file);
if (setup->group) eina_stringshare_del(setup->group);
if (setup->swallow) eina_stringshare_del(setup->swallow);
free(ed->processing);
ed->processing = NULL;
}
static void
_process_file(Ethumbd *ed)
{
_ethumbd_child_write_op_generate
(&ed->slave, ed->queue.current, ed->processing->file,
ed->processing->key, ed->processing->thumb, ed->processing->thumb_key);
}
static int
_get_next_on_queue(Ethumbd_Queue *queue)
{
int i, idx;
Ethumbd_Object *eobject;
i = queue->last;
i++;
if (i >= queue->count)
i = 0;
idx = queue->list[i];
eobject = &(queue->table[idx]);
while (!eobject->nqueue)
{
i = (i + 1) % queue->count;
idx = queue->list[i];
eobject = &(queue->table[idx]);
}
return queue->list[i];
}
static Eina_Bool
_process_queue_cb(void *data)
{
Ethumbd_Object *eobject;
int i;
Ethumbd *ed = data;
Ethumbd_Queue *queue = &ed->queue;
Ethumbd_Request *request;
if (ed->processing)
return 1;
if (!queue->nqueue)
{
ed->idler = NULL;
if (!queue->count)
_ethumbd_timeout_start(ed);
ed->idler = NULL;
return 0;
}
i = _get_next_on_queue(queue);
eobject = &(queue->table[i]);
request = eina_list_data_get(eobject->queue);
eobject->queue = eina_list_remove_list(eobject->queue, eobject->queue);
ed->queue.current = i;
DBG("processing file: \"%s:%s\"...", request->file,
request->key);
ed->processing = request;
if (request->id < 0)
_process_setup(ed);
else
{
_process_file(ed);
_ethumb_dbus_inc_min_id(eobject);
}
eobject->nqueue--;
queue->nqueue--;
queue->last = i;
return 1;
}
static void
_process_queue_start(Ethumbd *ed)
{
if (!ed->idler)
ed->idler = ecore_idler_add(_process_queue_cb, ed);
}
static void
_process_queue_stop(Ethumbd *ed)
{
if (ed->idler)
{
ecore_idler_del(ed->idler);
ed->idler = NULL;
}
}
static int
_ethumb_table_append(Ethumbd *ed)
{
int i;
char buf[1024];
Ethumbd_Queue *q = &ed->queue;
if (q->count == q->max_count)
{
int new_max = q->max_count + 5;
int start, size;
void *tmp;
start = q->max_count;
size = new_max - q->max_count;
tmp = realloc(q->table, new_max * sizeof(Ethumbd_Object));
if (!tmp)
{
CRIT("could not realloc q->table to %zd bytes: %s",
new_max * sizeof(Ethumbd_Object), strerror(errno));
return -1;
}
q->table = tmp;
memset(&q->table[start], 0, size * sizeof(Ethumbd_Object));
tmp = realloc(q->list, new_max * sizeof(int));
if (!tmp)
{
CRIT("could not realloc q->list to %zd bytes: %s",
new_max * sizeof(int), strerror(errno));
return -1;
}
q->list = tmp;
q->max_count = new_max;
}
for (i = 0; i < q->max_count; i++)
{
if (!q->table[i].used)
break;
}
snprintf(buf, sizeof(buf), "%s/%d", _ethumb_dbus_path, i);
q->table[i].used = 1;
q->table[i].path = eina_stringshare_add(buf);
q->table[i].max_id = -1;
q->table[i].min_id = -1;
q->list[q->count] = i;
q->count++;
DBG("new object: %s, idx = %d, count = %d", buf, i, q->count);
return i;
}
static inline int
_get_idx_for_path(const char *path)
{
int i;
int n;
n = sscanf(path, "/org/enlightenment/Ethumb/%d", &i);
if (!n)
return -1;
return i;
}
static void _name_owner_changed_cb(void *context, const char *bus, const char *old_id, const char *new_id);
static void
_ethumb_table_del(Ethumbd *ed, int i)
{
int j;
Eina_List *l;
Ethumbd_Queue *q = &ed->queue;
Ethumbd_Object_Data *odata;
eina_stringshare_del(q->table[i].path);
l = q->table[i].queue;
while (l)
{
Ethumbd_Request *request = l->data;
eina_stringshare_del(request->file);
eina_stringshare_del(request->key);
eina_stringshare_del(request->thumb);
eina_stringshare_del(request->thumb_key);
free(request);
l = eina_list_remove_list(l, l);
}
q->nqueue -= q->table[i].nqueue;
odata = edbus_service_object_data_del(q->table[i].iface, ODATA);
edbus_name_owner_changed_callback_del(ed->conn, ed->queue.table[i].client,
_name_owner_changed_cb, odata);
//this string was not been freed previously
eina_stringshare_del(ed->queue.table[i].client);
free(odata);
edbus_service_object_unregister(q->table[i].iface);
memset(&(q->table[i]), 0, sizeof(Ethumbd_Object));
for (j = 0; j < q->count; j++)
{
if (q->list[j] == i)
q->list[j] = q->list[q->count - 1];
}
q->count--;
_ethumbd_child_write_op_del(&ed->slave, i);
if (!q->count && !ed->processing)
_ethumbd_timeout_start(ed);
}
static void
_ethumb_table_clear(Ethumbd *ed)
{
int i;
for (i = 0; i < ed->queue.max_count; i++)
if (ed->queue.table[i].used)
_ethumb_table_del(ed, i);
}
static void
_name_owner_changed_cb(void *context, const char *bus, const char *old_id, const char *new_id)
{
Ethumbd_Object_Data *odata = context;
Ethumbd *ed = odata->ed;
DBG("NameOwnerChanged: name = %s, from = %s, to = %s", bus, old_id, new_id);
if (new_id[0])
return;
_ethumb_table_del(ed, odata->idx);
}
static const EDBus_Service_Interface_Desc client_desc = {
_ethumb_dbus_objects_interface, _ethumb_dbus_objects_methods,
_ethumb_dbus_objects_signals
};
static EDBus_Message *
_ethumb_dbus_ethumb_new_cb(const EDBus_Service_Interface *interface, const EDBus_Message *msg)
{
EDBus_Message *reply;
EDBus_Service_Interface *iface;
Ethumbd_Object_Data *odata;
int i;
const char *return_path = "";
const char *client;
Ethumbd *ed;
ed = edbus_service_object_data_get(interface, DAEMON);
client = edbus_message_sender_get(msg);
if (!client)
goto end_new;
i = _ethumb_table_append(ed);
if (i < 0)
goto end_new;
odata = calloc(1, sizeof(*odata));
odata->idx = i;
odata->ed = ed;
ed->queue.table[i].client = eina_stringshare_add(client);
return_path = ed->queue.table[i].path;
iface = edbus_service_interface_register(ed->conn, return_path, &client_desc);
if (!iface)
{
ERR("could not create dbus_object.");
free(odata);
return_path = "";
goto end_new;
}
edbus_service_object_data_set(iface, ODATA, odata);
ed->queue.table[i].iface = iface;
edbus_name_owner_changed_callback_add(ed->conn, client,
_name_owner_changed_cb, odata,
EINA_TRUE);
_ethumbd_child_write_op_new(&ed->slave, i);
_ethumbd_timeout_stop(ed);
end_new:
reply = edbus_message_method_return_new(msg);
edbus_message_arguments_append(reply, "o", return_path);
return reply;
}
static const EDBus_Method _ethumb_dbus_methods[] = {
{
"new", NULL, EDBUS_ARGS({"o", "path"}), _ethumb_dbus_ethumb_new_cb, 0
},
{ }
};
static const char *
_ethumb_dbus_get_bytearray(EDBus_Message_Iter *iter)
{
int length;
const char *result;
if (!edbus_message_iter_fixed_array_get(iter, 'y', &result,
&length))
{
ERR("not byte array element. Signature: %s",
edbus_message_iter_signature_get(iter));
return NULL;
}
if ((length == 0) || (result[0] == '\0'))
return NULL;
else
return eina_stringshare_add_length(result, length);
}
static void
_ethumb_dbus_append_bytearray(EDBus_Message_Iter *parent, EDBus_Message_Iter *array, const char *string)
{
int i, size;
if (!string)
string = "";
size = strlen(string) + 1;
for (i = 0; i < size; i++)
edbus_message_iter_basic_append(array, 'y', string[i]);
edbus_message_iter_container_close(parent, array);
}
static EDBus_Message *
_ethumb_dbus_queue_add_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply;
const char *file, *key, *thumb, *thumb_key;
Ethumbd_Object_Data *odata;
Ethumbd_Object *eobject;
Ethumbd *ed;
Ethumbd_Request *request;
int id = -1;
EDBus_Message_Iter *file_iter, *key_iter, *thumb_iter, *thumb_key_iter;
if (!edbus_message_arguments_get(msg, "iayayayay", &id, &file_iter,
&key_iter, &thumb_iter, &thumb_key_iter))
{
ERR("Error getting arguments.");
goto end;
}
file = _ethumb_dbus_get_bytearray(file_iter);
key = _ethumb_dbus_get_bytearray(key_iter);
thumb = _ethumb_dbus_get_bytearray(thumb_iter);
thumb_key = _ethumb_dbus_get_bytearray(thumb_key_iter);
if (!file)
{
eina_stringshare_del(key);
eina_stringshare_del(thumb);
eina_stringshare_del(thumb_key);
ERR("no filename given.");
goto end;
}
odata = edbus_service_object_data_get(iface, ODATA);
if (!odata)
{
eina_stringshare_del(file);
eina_stringshare_del(key);
eina_stringshare_del(thumb);
eina_stringshare_del(thumb_key);
ERR("could not get dbus_object data.");
goto end;
}
ed = odata->ed;
eobject = &(ed->queue.table[odata->idx]);
if (!_ethumb_dbus_check_id(eobject, id))
goto end;
request = calloc(1, sizeof(*request));
request->id = id;
request->file = file;
request->key = key;
request->thumb = thumb;
request->thumb_key = thumb_key;
eobject->queue = eina_list_append(eobject->queue, request);
eobject->nqueue++;
ed->queue.nqueue++;
_ethumb_dbus_inc_max_id(eobject, id);
_process_queue_start(ed);
end:
reply = edbus_message_method_return_new(msg);
edbus_message_arguments_append(reply, "i", id);
return reply;
}
static EDBus_Message *
_ethumb_dbus_queue_remove_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply;
int id;
Ethumbd_Object_Data *odata;
Ethumbd_Object *eobject;
Ethumbd_Request *request;
Ethumbd *ed;
Eina_Bool r = EINA_FALSE;
Eina_List *l;
if (!edbus_message_arguments_get(msg, "i", &id))
{
ERR("Error getting arguments.");
goto end;
}
odata = edbus_service_object_data_get(iface, ODATA);
if (!odata)
{
ERR("could not get dbus_object data.");
goto end;
}
ed = odata->ed;
eobject = &ed->queue.table[odata->idx];
l = eobject->queue;
while (l)
{
request = l->data;
if (id == request->id)
break;
l = l->next;
}
if (l)
{
r = EINA_TRUE;
eina_stringshare_del(request->file);
eina_stringshare_del(request->key);
eina_stringshare_del(request->thumb);
eina_stringshare_del(request->thumb_key);
free(request);
eobject->queue = eina_list_remove_list(eobject->queue, l);
eobject->nqueue--;
ed->queue.nqueue--;
_ethumb_dbus_inc_min_id(eobject);
}
end:
reply = edbus_message_method_return_new(msg);
edbus_message_arguments_append(reply, "b", r);
return reply;
}
static EDBus_Message *
_ethumb_dbus_queue_clear_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
Ethumbd_Object_Data *odata;
Ethumbd_Object *eobject;
Ethumbd *ed;
Eina_List *l;
odata = edbus_service_object_data_get(iface, ODATA);
if (!odata)
{
ERR("could not get dbus_object data.");
goto end;
}
ed = odata->ed;
eobject = &ed->queue.table[odata->idx];
l = eobject->queue;
while (l)
{
Ethumbd_Request *request = l->data;
eina_stringshare_del(request->file);
eina_stringshare_del(request->key);
eina_stringshare_del(request->thumb);
eina_stringshare_del(request->thumb_key);
free(request);
l = eina_list_remove_list(l, l);
}
ed->queue.nqueue -= eobject->nqueue;
eobject->nqueue = 0;
end:
return edbus_message_method_return_new(msg);
}
static EDBus_Message *
_ethumb_dbus_delete_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply;
Ethumbd_Object_Data *odata;
Ethumbd *ed;
reply = edbus_message_method_return_new(msg);
odata = edbus_service_object_data_get(iface, ODATA);
if (!odata)
{
ERR("could not get dbus_object data for del_cb.");
return reply;
}
ed = odata->ed;
_ethumb_table_del(ed, odata->idx);
free(odata);
return reply;
}
static int
_ethumb_dbus_fdo_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
int fdo;
if (!edbus_message_iter_arguments_get(variant, "i", &fdo))
{
ERR("invalid param for fdo_set.");
return 0;
}
DBG("setting fdo to: %d", fdo);
request->setup.flags.fdo = 1;
request->setup.fdo = fdo;
return 1;
}
static int
_ethumb_dbus_size_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
EDBus_Message_Iter *st;
int w, h;
if (!edbus_message_iter_arguments_get(variant, "(ii)", &st))
{
ERR("invalid param for size_set.");
return 0;
}
edbus_message_iter_arguments_get(st, "ii", &w, &h);
DBG("setting size to: %dx%d", w, h);
request->setup.flags.size = 1;
request->setup.tw = w;
request->setup.th = h;
return 1;
}
static int
_ethumb_dbus_format_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
int format;
if (!edbus_message_iter_arguments_get(variant, "i", &format))
{
ERR("invalid param for format_set.");
return 0;
}
DBG("setting format to: %d", format);
request->setup.flags.format = 1;
request->setup.format = format;
return 1;
}
static int
_ethumb_dbus_aspect_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
int aspect;
if (!edbus_message_iter_arguments_get(variant, "i", &aspect))
{
ERR("invalid param for aspect_set.");
return 0;
}
DBG("setting aspect to: %d", aspect);
request->setup.flags.aspect = 1;
request->setup.aspect = aspect;
return 1;
}
static int
_ethumb_dbus_orientation_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
int orientation;
if (!edbus_message_iter_arguments_get(variant, "i", &orientation))
{
ERR("invalid param for orientation_set.");
return 0;
}
DBG("setting orientation to: %d", orientation);
request->setup.flags.orientation = 1;
request->setup.orientation = orientation;
return 1;
}
static int
_ethumb_dbus_crop_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
EDBus_Message_Iter *st;
double x, y;
if (!edbus_message_iter_arguments_get(variant, "(dd)", &st))
{
ERR("invalid param for crop_set.");
return 0;
}
edbus_message_iter_arguments_get(st, "dd", &x, &y);
DBG("setting crop to: %3.2f,%3.2f", x, y);
request->setup.flags.crop = 1;
request->setup.cx = x;
request->setup.cy = y;
return 1;
}
static int
_ethumb_dbus_quality_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
int quality;
if (!edbus_message_iter_arguments_get(variant, "i", &quality))
{
ERR("invalid param for quality_set.");
return 0;
}
DBG("setting quality to: %d", quality);
request->setup.flags.quality = 1;
request->setup.quality = quality;
return 1;
}
static int
_ethumb_dbus_compress_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
int compress;
if (!edbus_message_iter_arguments_get(variant, "i", &compress))
{
ERR("invalid param for compress_set.");
return 0;
}
DBG("setting compress to: %d", compress);
request->setup.flags.compress = 1;
request->setup.compress = compress;
return 1;
}
static int
_ethumb_dbus_frame_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
EDBus_Message_Iter *_struct, *file_iter, *group_iter, *swallow_iter;
const char *file, *group, *swallow;
if (!edbus_message_iter_arguments_get(variant, "(ayayay)", &_struct))
{
ERR("invalid param for frame_set.");
return 0;
}
edbus_message_iter_arguments_get(_struct, "ayayay", &file_iter, &group_iter, &swallow_iter);
file = _ethumb_dbus_get_bytearray(file_iter);
group = _ethumb_dbus_get_bytearray(group_iter);
swallow = _ethumb_dbus_get_bytearray(swallow_iter);
DBG("setting frame to \"%s:%s:%s\"", file, group, swallow);
request->setup.flags.frame = 1;
request->setup.theme_file = file;
request->setup.group = group;
request->setup.swallow = swallow;
return 1;
}
static int
_ethumb_dbus_directory_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
const char *directory;
EDBus_Message_Iter *array;
if (!edbus_message_iter_arguments_get(variant, "ay", &array))
{
ERR("invalid param for dir_path_set.");
return 0;
}
directory = _ethumb_dbus_get_bytearray(array);
DBG("setting directory to: %s", directory);
request->setup.flags.directory = 1;
request->setup.directory = directory;
return 1;
}
static int
_ethumb_dbus_category_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
const char *category;
EDBus_Message_Iter *array;
if (!edbus_message_iter_arguments_get(variant, "ay", &array))
{
ERR("invalid param for category.");
return 0;
}
category = _ethumb_dbus_get_bytearray(array);
DBG("setting category to: %s", category);
request->setup.flags.category = 1;
request->setup.category = category;
return 1;
}
static int
_ethumb_dbus_video_time_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
double video_time;
if (!edbus_message_iter_arguments_get(variant, "d", &video_time))
{
ERR("invalid param for video_time_set.");
return 0;
}
DBG("setting video_time to: %3.2f", video_time);
request->setup.flags.video_time = 1;
request->setup.video_time = video_time;
return 1;
}
static int
_ethumb_dbus_video_start_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
double video_start;
if (!edbus_message_iter_arguments_get(variant, "d", &video_start))
{
ERR("invalid param for video_start_set.");
return 0;
}
DBG("setting video_start to: %3.2f", video_start);
request->setup.flags.video_start = 1;
request->setup.video_start = video_start;
return 1;
}
static int
_ethumb_dbus_video_interval_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
double video_interval;
if (!edbus_message_iter_arguments_get(variant, "d", &video_interval))
{
ERR("invalid param for video_interval_set.");
return 0;
}
DBG("setting video_interval to: %3.2f", video_interval);
request->setup.flags.video_interval = 1;
request->setup.video_interval = video_interval;
return 1;
}
static int
_ethumb_dbus_video_ntimes_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
unsigned int video_ntimes;
if (!edbus_message_iter_arguments_get(variant, "u", &video_ntimes))
{
ERR("invalid param for video_ntimes_set.");
return 0;
}
DBG("setting video_ntimes to: %3.2d", video_ntimes);
request->setup.flags.video_ntimes = 1;
request->setup.video_ntimes = video_ntimes;
return 1;
}
static int
_ethumb_dbus_video_fps_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
unsigned int video_fps;
if (!edbus_message_iter_arguments_get(variant, "u", &video_fps))
{
ERR("invalid param for video_fps_set.");
return 0;
}
DBG("setting video_fps to: %3.2d", video_fps);
request->setup.flags.video_fps = 1;
request->setup.video_fps = video_fps;
return 1;
}
static int
_ethumb_dbus_document_page_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
{
unsigned int document_page;
if (!edbus_message_iter_arguments_get(variant, "u", &document_page))
{
ERR("invalid param for document_page_set.");
return 0;
}
DBG("setting document_page to: %d", document_page);
request->setup.flags.document_page = 1;
request->setup.document_page = document_page;
return 1;
}
static struct
{
const char *option;
int (*setup_func)(Ethumbd_Object *eobject, EDBus_Message_Iter *variant, Ethumbd_Request *request);
} _option_cbs[] = {
{"fdo", _ethumb_dbus_fdo_set},
{"size", _ethumb_dbus_size_set},
{"format", _ethumb_dbus_format_set},
{"aspect", _ethumb_dbus_aspect_set},
{"orientation", _ethumb_dbus_orientation_set},
{"crop", _ethumb_dbus_crop_set},
{"quality", _ethumb_dbus_quality_set},
{"compress", _ethumb_dbus_compress_set},
{"frame", _ethumb_dbus_frame_set},
{"directory", _ethumb_dbus_directory_set},
{"category", _ethumb_dbus_category_set},
{"video_time", _ethumb_dbus_video_time_set},
{"video_start", _ethumb_dbus_video_start_set},
{"video_interval", _ethumb_dbus_video_interval_set},
{"video_ntimes", _ethumb_dbus_video_ntimes_set},
{"video_fps", _ethumb_dbus_video_fps_set},
{"document_page", _ethumb_dbus_document_page_set},
{NULL, NULL}
};
static int
_ethumb_dbus_ethumb_setup_parse_element(Ethumbd_Object *eobject, EDBus_Message_Iter *data, Ethumbd_Request *request)
{
EDBus_Message_Iter *variant;
const char *option;
int i, r;
edbus_message_iter_arguments_get(data, "sv", &option, &variant);
r = 0;
for (i = 0; _option_cbs[i].option; i++)
if (!strcmp(_option_cbs[i].option, option))
{
r = 1;
break;
}
if (!r)
{
ERR("ethumb_setup invalid option: %s", option);
return 0;
}
return _option_cbs[i].setup_func(eobject, variant, request);
}
static EDBus_Message *
_ethumb_dbus_ethumb_setup_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
{
EDBus_Message *reply;
Ethumbd_Object_Data *odata;
Ethumbd *ed;
Ethumbd_Object *eobject;
Ethumbd_Request *request;
Eina_Bool r = EINA_FALSE;
EDBus_Message_Iter *array;
EDBus_Message_Iter *data;
if (!edbus_message_arguments_get(msg, "a{sv}", &array))
{
ERR("could not get dbus_object data for setup_cb.");
goto end;
}
odata = edbus_service_object_data_get(iface, ODATA);
if (!odata)
{
ERR("could not get dbus_object data for setup_cb.");
goto end;
}
ed = odata->ed;
eobject = &ed->queue.table[odata->idx];
request = calloc(1, sizeof(*request));
request->id = -1;
r = EINA_TRUE;
while (edbus_message_iter_get_and_next(array, 'r', &data) && r)
{
if (!_ethumb_dbus_ethumb_setup_parse_element(eobject, data, request))
r = EINA_FALSE;
}
eobject->queue = eina_list_append(eobject->queue, request);
eobject->nqueue++;
ed->queue.nqueue++;
end:
reply = edbus_message_method_return_new(msg);
edbus_message_arguments_append(reply, "b", r);
return reply;
}
static void
_ethumb_dbus_generated_signal(Ethumbd *ed, int *id, const char *thumb_path, const char *thumb_key, Eina_Bool success)
{
EDBus_Message *sig;
EDBus_Service_Interface *iface;
EDBus_Message_Iter *iter, *iter_path, *iter_key;
int id32;
id32 = *id;
iface = ed->queue.table[ed->queue.current].iface;
sig = edbus_service_signal_new(iface, ETHUMB_DBUS_OBJECTS_SIGNAL_GENERATED);
iter = edbus_message_iter_get(sig);
edbus_message_iter_arguments_append(iter, "iay", id32, &iter_path);
_ethumb_dbus_append_bytearray(iter, iter_path, thumb_path);
edbus_message_iter_arguments_append(iter, "ay", &iter_key);
_ethumb_dbus_append_bytearray(iter, iter_key, thumb_key);
edbus_message_iter_arguments_append(iter, "b", success);
edbus_service_signal_send(iface, sig);
}
static const EDBus_Service_Interface_Desc server_desc = {
_ethumb_dbus_interface, _ethumb_dbus_methods
};
static void
_ethumb_dbus_request_name_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending EINA_UNUSED)
{
EDBus_Service_Interface *iface;
const char *errname, *errmsg;
Ethumbd *ed = data;
if (edbus_message_error_get(msg, &errname, &errmsg))
{
ERR("request name error: %s %s", errname, errmsg);
edbus_connection_unref(ed->conn);
return;
}
iface = edbus_service_interface_register(ed->conn, _ethumb_dbus_path,
&server_desc);
EINA_SAFETY_ON_NULL_RETURN(iface);
edbus_service_object_data_set(iface, DAEMON, ed);
_ethumbd_timeout_start(ed);
}
static int
_ethumb_dbus_setup(Ethumbd *ed)
{
edbus_name_request(ed->conn, _ethumb_dbus_bus_name, 0,
_ethumb_dbus_request_name_cb, ed);
return 1;
}
static void
_ethumb_dbus_finish(Ethumbd *ed)
{
_process_queue_stop(ed);
_ethumb_table_clear(ed);
edbus_connection_unref(ed->conn);
free(ed->queue.table);
free(ed->queue.list);
}
static Eina_Bool
_ethumbd_slave_spawn(Ethumbd_Slave *slave, Ethumbd *ed)
{
char buf[PATH_MAX];
slave->bufcmd = NULL;
slave->scmd = 0;
snprintf(buf, sizeof(buf), "%s/ethumb/utils/"MODULE_ARCH"/ethumbd_slave",
eina_prefix_lib_get(_pfx));
slave->exe = ecore_exe_pipe_run(buf,
ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE, ed);
if (!slave->exe)
{
ERR("could not create slave.");
return 0;
}
return 1;
}
int
main(int argc, char *argv[])
{
Eina_Bool quit_option = 0;
int exit_value = 0;
int arg_idx;
Ethumbd ed;
int child;
double timeout = -1;
memset(&ed, 0, sizeof(ed));
ecore_init();
eina_init();
ethumb_init();
if (_log_domain < 0)
{
_log_domain = eina_log_domain_register("ethumbd", NULL);
if (_log_domain < 0)
{
EINA_LOG_CRIT("could not register log domain 'ethumbd'");
exit_value = -8;
goto finish;
}
}
_pfx = eina_prefix_new(argv[0], ethumb_init,
"ETHUMB", "ethumb", "checkme",
PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
if (!_pfx)
{
ERR("Could not get ethumb installation prefix.");
exit_value = -7;
goto finish;
}
ed.data_cb = ecore_event_handler_add(ECORE_EXE_EVENT_DATA,
_ethumbd_slave_data_read_cb, &ed);
ed.del_cb = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
_ethumbd_slave_del_cb, &ed);
child = _ethumbd_slave_spawn(&ed.slave, &ed);
if (!child)
{
exit_value = -6;
goto finish;
}
if (child == 2)
{
exit_value = 0;
goto finish;
}
if (!edbus_init())
{
ERR("could not init edbus.");
exit_value = -1;
goto finish;
}
Ecore_Getopt_Value values[] = {
ECORE_GETOPT_VALUE_DOUBLE(timeout),
ECORE_GETOPT_VALUE_BOOL(quit_option),
ECORE_GETOPT_VALUE_BOOL(quit_option),
ECORE_GETOPT_VALUE_BOOL(quit_option),
ECORE_GETOPT_VALUE_BOOL(quit_option),
ECORE_GETOPT_VALUE_NONE
};
arg_idx = ecore_getopt_parse(&optdesc, values, argc, argv);
if (arg_idx < 0)
{
ERR("Could not parse arguments.");
exit_value = -2;
goto finish;
}
if (quit_option)
goto finish;
ed.conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
if (!ed.conn)
{
ERR("could not connect to session bus.");
exit_value = -3;
goto finish_edbus;
}
ed.timeout = timeout;
if (!_ethumb_dbus_setup(&ed))
{
edbus_connection_unref(ed.conn);
ERR("could not setup dbus connection.");
exit_value = -5;
goto finish_edbus;
}
ecore_main_loop_begin();
_ethumb_dbus_finish(&ed);
finish_edbus:
if (_log_domain >= 0)
{
eina_log_domain_unregister(_log_domain);
_log_domain = -1;
}
edbus_shutdown();
finish:
if (ed.slave.exe)
ecore_exe_quit(ed.slave.exe);
if (_pfx) eina_prefix_free(_pfx);
ethumb_shutdown();
eina_init();
ecore_shutdown();
return exit_value;
}