diff options
Diffstat (limited to 'pysource.c')
-rw-r--r-- | pysource.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/pysource.c b/pysource.c new file mode 100644 index 0000000..f3a0663 --- /dev/null +++ b/pysource.c @@ -0,0 +1,156 @@ +#include <Python.h> +#include "pyirssi.h" +#include "pysource.h" + +typedef struct _PY_SOURCE_REC +{ + int once; + int tag; + int fd; + GSList **container; /* "container" points to a list owned by a Script object */ + PyObject *handler; + PyObject *data; +} PY_SOURCE_REC; + +static PY_SOURCE_REC *py_source_new(GSList **list, int once, PyObject *handler, PyObject *data) +{ + PY_SOURCE_REC *rec; + + rec = g_new0(PY_SOURCE_REC, 1); + rec->once = once; + rec->fd = -1; + rec->handler = handler; + rec->data = data; + rec->container = list; + + Py_INCREF(handler); + Py_XINCREF(data); + + return rec; +} + +static void py_source_destroy(PY_SOURCE_REC *rec) +{ + g_source_remove(rec->tag); + Py_DECREF(rec->handler); + Py_XDECREF(rec->data); + g_free(rec); +} + +static int py_source_proxy(PY_SOURCE_REC *rec) +{ + char args[3] = {0,0,0}; + int fd; + PyObject *ret; + PyObject *handler, *data; + + /* Copy data out of the rec (there's not much). The rec may be deleted in + the if block below or by the Python code executed. Protect handler & data + with INCREF. + */ + + fd = rec->fd; + handler = rec->handler; + data = rec->data; + Py_INCREF(handler); + Py_XINCREF(data); + + if (rec->once) + { + *rec->container = g_slist_remove(*rec->container, rec); + py_source_destroy(rec); + } + + /* call python function with fd and/or data if available. + IO handler will be called with either "iO" or "i". + Timeout with "O" or "". + */ + + if (fd >= 0) + { + /* IO handler */ + args[0] = 'i'; + if (data) + args[1] = 'O'; + + ret = PyObject_CallFunction(handler, args, fd, data); + } + else + { + /* Timeout handler */ + if (data) + args[0] = 'O'; + + ret = PyObject_CallFunction(handler, args, data); + } + + if (!ret) + PyErr_Print(); + else + Py_DECREF(ret); + + Py_DECREF(handler); + Py_XDECREF(data); + + return 1; +} + +int pysource_timeout_add_list(GSList **list, int msecs, PyObject *func, PyObject *data, int once) +{ + PY_SOURCE_REC *rec; + + g_return_val_if_fail(func != NULL, -1); + + rec = py_source_new(list, once, func, data); + rec->tag = g_timeout_add(msecs, (GSourceFunc)py_source_proxy, rec); + + *list = g_slist_append(*list, rec); + + return rec->tag; +} + +int pysource_input_add_list(GSList **list, int fd, int cond, PyObject *func, PyObject *data, int once) +{ + PY_SOURCE_REC *rec; + GIOChannel *channel; + + g_return_val_if_fail(func != NULL, 1); + rec = py_source_new(list, once, func, data); + rec->fd = fd; + channel = g_io_channel_unix_new(fd); + rec->tag = g_input_add(channel, cond, (GInputFunction)py_source_proxy, rec); + g_io_channel_unref(channel); + + *list = g_slist_append(*list, rec); + + return rec->tag; +} + +int pysource_remove_tag(GSList **list, int handle) +{ + GSList *node; + + for (node = *list; node != NULL; node = node->next) + { + PY_SOURCE_REC *rec = node->data; + + if (rec->tag == handle) + { + py_source_destroy(rec); + *list = g_slist_delete_link(*list, node); + + return 1; + } + } + + return 0; +} + +void pysource_remove_list(GSList *list) +{ + GSList *node; + + for (node = list; node != NULL; node = node->next) + py_source_destroy(node->data); +} + |