From bf49647a03923975eb24ce634dae8254553db8de Mon Sep 17 00:00:00 2001 From: Johan Dahlin Date: Mon, 21 Jul 2008 17:27:22 +0000 Subject: Move over Source, IOChannel, Idle, Timeout and PollFD to glib from 2008-07-21 Johan Dahlin * glib/Makefile.am: * glib/glibmodule.c (pyg_idle_add), (pyg_timeout_add), (pyg_timeout_add_seconds), (pyg_io_add_watch), (pyglib_register_api), (pyglib_register_error), (pyglib_register_version_tuples), (init_glib): * glib/pygiochannel.c (py_io_channel_next), (py_io_channel_shutdown), (py_io_channel_set_encoding), (py_io_channel_read_chars), (py_io_channel_write_chars), (py_io_channel_write_lines), (py_io_channel_flush), (py_io_channel_set_flags), (py_io_channel_read_line), (py_io_channel_read_lines), (py_io_channel_seek), (py_io_channel_init), (pyglib_iochannel_register_types): * glib/pygiochannel.h: * glib/pyglib-private.h: * glib/pyglib.c (pyglib_threads_enabled), (pyglib_gil_state_ensure), (pyglib_gil_state_release), (pyglib_enable_threads), (pyglib_block_threads), (pyglib_unblock_threads), (pyglib_set_thread_block_funcs), (pyglib_handler_marshal), (pyglib_destroy_notify): * glib/pyglib.h: * glib/pygsource.c (pyg_source_set_callback), (pyglib_source_register_types): * glib/pygsource.h: * glib/pygspawn.c (pyglib_spawn_register_types): * glib/pygspawn.h: * gobject/Makefile.am: * gobject/__init__.py: * gobject/gobjectmodule.c (pyg_set_thread_block_funcs), (init_gobject): * gobject/pygiochannel.c: * gobject/pygobject-private.h: * gobject/pygsource.c: Move over Source, IOChannel, Idle, Timeout and PollFD to glib from gobject. Clean up and add a bit of new api for glib. svn path=/trunk/; revision=846 --- ChangeLog | 38 ++ glib/Makefile.am | 12 +- glib/glibmodule.c | 79 +--- glib/pygiochannel.c | 818 +++++++++++++++++++++++++++++++++++++++++ glib/pygiochannel.h | 29 ++ glib/pyglib-private.h | 6 +- glib/pyglib.c | 96 +++++ glib/pyglib.h | 6 + glib/pygsource.c | 860 ++++++++++++++++++++++++++++++++++++++++++++ glib/pygsource.h | 39 ++ glib/pygspawn.c | 2 +- glib/pygspawn.h | 2 +- gobject/Makefile.am | 2 - gobject/__init__.py | 4 +- gobject/gobjectmodule.c | 10 +- gobject/pygiochannel.c | 812 ----------------------------------------- gobject/pygobject-private.h | 29 +- gobject/pygsource.c | 847 ------------------------------------------- 18 files changed, 1931 insertions(+), 1760 deletions(-) create mode 100644 glib/pygiochannel.c create mode 100644 glib/pygiochannel.h create mode 100644 glib/pygsource.c create mode 100644 glib/pygsource.h delete mode 100644 gobject/pygiochannel.c delete mode 100644 gobject/pygsource.c diff --git a/ChangeLog b/ChangeLog index e39bc5f..0df0122 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +2008-07-21 Johan Dahlin + + * glib/Makefile.am: + * glib/glibmodule.c (pyg_idle_add), (pyg_timeout_add), + (pyg_timeout_add_seconds), (pyg_io_add_watch), + (pyglib_register_api), (pyglib_register_error), + (pyglib_register_version_tuples), (init_glib): + * glib/pygiochannel.c (py_io_channel_next), + (py_io_channel_shutdown), (py_io_channel_set_encoding), + (py_io_channel_read_chars), (py_io_channel_write_chars), + (py_io_channel_write_lines), (py_io_channel_flush), + (py_io_channel_set_flags), (py_io_channel_read_line), + (py_io_channel_read_lines), (py_io_channel_seek), + (py_io_channel_init), (pyglib_iochannel_register_types): + * glib/pygiochannel.h: + * glib/pyglib-private.h: + * glib/pyglib.c (pyglib_threads_enabled), + (pyglib_gil_state_ensure), (pyglib_gil_state_release), + (pyglib_enable_threads), (pyglib_block_threads), + (pyglib_unblock_threads), (pyglib_set_thread_block_funcs), + (pyglib_handler_marshal), (pyglib_destroy_notify): + * glib/pyglib.h: + * glib/pygsource.c (pyg_source_set_callback), + (pyglib_source_register_types): + * glib/pygsource.h: + * glib/pygspawn.c (pyglib_spawn_register_types): + * glib/pygspawn.h: + * gobject/Makefile.am: + * gobject/__init__.py: + * gobject/gobjectmodule.c (pyg_set_thread_block_funcs), + (init_gobject): + * gobject/pygiochannel.c: + * gobject/pygobject-private.h: + * gobject/pygsource.c: + Move over Source, IOChannel, Idle, Timeout and PollFD to glib from + gobject. + Clean up and add a bit of new api for glib. + 2008-07-21 Johan Dahlin * configure.ac: diff --git a/glib/Makefile.am b/glib/Makefile.am index e32d24d..c2cbf47 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -30,10 +30,16 @@ _glib_la_LDFLAGS = $(common_ldflags) -export-symbols-regex init_glib _glib_la_LIBADD = $(GLIB_LIBS) libpyglib-2.0.la _glib_la_SOURCES = \ glibmodule.c \ - pygspawn.c \ - pygspawn.h \ + pygiochannel.c \ + pygiochannel.h \ pygmaincontext.c \ - pygmainloop.c + pygmaincontext.h \ + pygmainloop.c \ + pygmainloop.h \ + pygsource.c \ + pygsource.h \ + pygspawn.c \ + pygspawn.h if PLATFORM_WIN32 _glib_la_CFLAGS += -DPLATFORM_WIN32 diff --git a/glib/glibmodule.c b/glib/glibmodule.c index 6892d1a..0281524 100644 --- a/glib/glibmodule.c +++ b/glib/glibmodule.c @@ -30,33 +30,16 @@ #include "pyglib.h" #include "pyglib-private.h" +#include "pygiochannel.h" #include "pygmaincontext.h" #include "pygmainloop.h" +#include "pygsource.h" #include "pygspawn.h" #define PYGLIB_MAJOR_VERSION PYGOBJECT_MAJOR_VERSION #define PYGLIB_MINOR_VERSION PYGOBJECT_MINOR_VERSION #define PYGLIB_MICRO_VERSION PYGOBJECT_MICRO_VERSION -/** - * pyg_destroy_notify: - * @user_data: a PyObject pointer. - * - * A function that can be used as a GDestroyNotify callback that will - * call Py_DECREF on the data. - */ -void -pyg_destroy_notify(gpointer user_data) -{ - PyObject *obj = (PyObject *)user_data; - PyGILState_STATE state; - - state = pyglib_gil_state_ensure(); - Py_DECREF(obj); - pyglib_gil_state_release(state); -} - - /* ---------------- glib module functions -------------------- */ @@ -100,33 +83,6 @@ get_handler_priority(gint *priority, PyObject *kwargs) return 0; } -gboolean -pyg_handler_marshal(gpointer user_data) -{ - PyObject *tuple, *ret; - gboolean res; - PyGILState_STATE state; - - g_return_val_if_fail(user_data != NULL, FALSE); - - state = pyglib_gil_state_ensure(); - - tuple = (PyObject *)user_data; - ret = PyObject_CallObject(PyTuple_GetItem(tuple, 0), - PyTuple_GetItem(tuple, 1)); - if (!ret) { - PyErr_Print(); - res = FALSE; - } else { - res = PyObject_IsTrue(ret); - Py_DECREF(ret); - } - - pyglib_gil_state_release(state); - - return res; -} - static PyObject * pyg_idle_add(PyObject *self, PyObject *args, PyObject *kwargs) { @@ -160,8 +116,8 @@ pyg_idle_add(PyObject *self, PyObject *args, PyObject *kwargs) data = Py_BuildValue("(ON)", callback, cbargs); if (data == NULL) return NULL; - handler_id = g_idle_add_full(priority, pyg_handler_marshal, data, - pyg_destroy_notify); + handler_id = g_idle_add_full(priority, pyglib_handler_marshal, data, + pyglib_destroy_notify); return PyInt_FromLong(handler_id); } @@ -200,8 +156,8 @@ pyg_timeout_add(PyObject *self, PyObject *args, PyObject *kwargs) if (data == NULL) return NULL; handler_id = g_timeout_add_full(priority, interval, - pyg_handler_marshal, data, - pyg_destroy_notify); + pyglib_handler_marshal, data, + pyglib_destroy_notify); return PyInt_FromLong(handler_id); } @@ -239,8 +195,8 @@ pyg_timeout_add_seconds(PyObject *self, PyObject *args, PyObject *kwargs) if (data == NULL) return NULL; handler_id = g_timeout_add_seconds_full(priority, interval, - pyg_handler_marshal, data, - pyg_destroy_notify); + pyglib_handler_marshal, data, + pyglib_destroy_notify); return PyInt_FromLong(handler_id); } @@ -328,7 +284,7 @@ pyg_io_add_watch(PyObject *self, PyObject *args, PyObject *kwargs) iochannel = g_io_channel_unix_new(fd); handler_id = g_io_add_watch_full(iochannel, priority, condition, iowatch_marshal, data, - (GDestroyNotify)pyg_destroy_notify); + (GDestroyNotify)pyglib_destroy_notify); g_io_channel_unref(iochannel); return PyInt_FromLong(handler_id); @@ -613,7 +569,7 @@ struct _PyGLib_Functions pyglib_api_functions = { }; static void -pyg_register_api(PyObject *d) +pyglib_register_api(PyObject *d) { PyObject *o; @@ -626,7 +582,7 @@ pyg_register_api(PyObject *d) } static void -pyg_register_error(PyObject *d) +pyglib_register_error(PyObject *d) { PyObject *dict; PyObject *gerror_class; @@ -644,7 +600,7 @@ pyg_register_error(PyObject *d) } static void -pyg_register_version_tuples(PyObject *d) +pyglib_register_version_tuples(PyObject *d) { PyObject *o; @@ -671,11 +627,12 @@ init_glib(void) m = Py_InitModule("glib._glib", pyglib_functions); d = PyModule_GetDict(m); - pyg_register_api(d); - pyg_register_error(d); - pyg_register_version_tuples(d); - pyg_spawn_register_types(d); - + pyglib_register_api(d); + pyglib_register_error(d); + pyglib_register_version_tuples(d); + pyglib_iochannel_register_types(d); pyglib_mainloop_register_types(d); pyglib_maincontext_register_types(d); + pyglib_source_register_types(d); + pyglib_spawn_register_types(d); } diff --git a/glib/pygiochannel.c b/glib/pygiochannel.c new file mode 100644 index 0000000..609cdab --- /dev/null +++ b/glib/pygiochannel.c @@ -0,0 +1,818 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include /* for PyMemberDef */ + +#include "pyglib.h" +#include "pyglib-private.h" + +typedef struct { + PyObject_HEAD + GIOChannel *channel; + int softspace; /* to make print >> chan, "foo" ... work */ +} PyGIOChannel; + +static PyObject* +py_io_channel_next(PyGIOChannel *self) +{ + PyObject* ret_obj = NULL; + gsize length = 0, terminator_pos; + gchar *str_return = NULL; + GError *error = NULL; + GIOStatus status; + + status = g_io_channel_read_line(self->channel, &str_return, &length, + &terminator_pos, &error); + if (pyglib_error_check(&error)) + return NULL; + + if (status == G_IO_STATUS_EOF) { + PyErr_SetString(PyExc_StopIteration, "EOF"); + return NULL; + } + + ret_obj = PyString_FromStringAndSize(str_return, length); + g_free(str_return); + return ret_obj; + +} + +static int +py_io_channel_compare(PyGIOChannel *self, PyGIOChannel *v) +{ + if (self->channel == v->channel) return 0; + if (self->channel > v->channel) return -1; + return 1; +} + +static PyObject* +py_io_channel_get_iter(PyObject *self) +{ + Py_INCREF(self); + return self; +} + +static long +py_io_channel_hash(PyGIOChannel *self) +{ + return (long) self->channel; +} + +static void +py_io_channel_dealloc(PyGIOChannel *self) +{ + if (self->channel) + g_io_channel_unref(self->channel); + PyObject_DEL(self); +} + +static PyObject* +py_io_channel_shutdown(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "flush", NULL }; + GIOStatus ret; + PyObject* flush = Py_True; + GError* error = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:gobject.IOChannel.shutdown", kwlist, &flush)) + return NULL; + + ret = g_io_channel_shutdown(self->channel, PyObject_IsTrue(flush), &error); + if (pyglib_error_check(&error)) + return NULL; + + return PyInt_FromLong(ret); +} + +/* character encoding conversion involved functions. + */ + +static PyObject* +py_io_channel_set_buffer_size(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "size", NULL }; + int size; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gobject.IOChannel.set_buffer_size", kwlist, &size)) + return NULL; + + g_io_channel_set_buffer_size(self->channel, size); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +py_io_channel_get_buffer_size(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { NULL }; + int size; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gobject.IOChannel.get_buffer_size", kwlist)) + return NULL; + + size = g_io_channel_get_buffer_size(self->channel); + + return PyInt_FromLong(size); +} + +static PyObject* +py_io_channel_set_buffered(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "buffered", NULL }; + int buffered; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gobject.IOChannel.set_buffered", kwlist, &buffered)) + return NULL; + + g_io_channel_set_buffered(self->channel, buffered); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +py_io_channel_get_buffered(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { NULL }; + int buffered; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.get_buffered", kwlist)) + return NULL; + + buffered = g_io_channel_get_buffered(self->channel); + + return PyInt_FromLong(buffered); +} + +static PyObject* +py_io_channel_set_encoding(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "encoding", NULL }; + const char* encoding; + GError* error = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z:gobject.IOChannel.set_encoding", kwlist, &encoding)) + return NULL; + + g_io_channel_set_encoding(self->channel, encoding, &error); + if (pyglib_error_check(&error)) + return NULL; + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +py_io_channel_get_encoding(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { NULL }; + const char* encoding; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.get_encoding", kwlist)) + return NULL; + + encoding = g_io_channel_get_encoding(self->channel); + + if (encoding == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + + return PyString_FromString(encoding); +} + +#define CHUNK_SIZE (8 * 1024) + +static PyObject* +py_io_channel_read_chars(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "max_count", NULL }; + int max_count = -1; + PyObject* ret_obj = NULL; + gsize total_read = 0; + GError* error = NULL; + GIOStatus status = G_IO_STATUS_NORMAL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:gobject.IOChannel.read", kwlist, &max_count)) + return NULL; + + if (max_count == 0) + return PyString_FromString(""); + + while (status == G_IO_STATUS_NORMAL + && (max_count == -1 || total_read < max_count)) { + gsize single_read; + char* buf; + gsize buf_size; + + if (max_count == -1) + buf_size = CHUNK_SIZE; + else { + buf_size = max_count - total_read; + if (buf_size > CHUNK_SIZE) + buf_size = CHUNK_SIZE; + } + + if ( ret_obj == NULL ) { + ret_obj = PyString_FromStringAndSize((char *)NULL, buf_size); + if (ret_obj == NULL) + goto failure; + } + else if (buf_size + total_read > PyString_GET_SIZE(ret_obj)) { + if (_PyString_Resize(&ret_obj, buf_size + total_read) == -1) + goto failure; + } + + buf = PyString_AS_STRING(ret_obj) + total_read; + + pyglib_unblock_threads(); + status = g_io_channel_read_chars(self->channel, buf, buf_size, + &single_read, &error); + pyglib_block_threads(); + if (pyglib_error_check(&error)) + goto failure; + + total_read += single_read; + } + + if ( total_read != PyString_GET_SIZE(ret_obj) ) { + if (_PyString_Resize(&ret_obj, total_read) == -1) + goto failure; + } + return ret_obj; + + failure: + Py_XDECREF(ret_obj); + return NULL; +} + +static PyObject* +py_io_channel_write_chars(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "buf", NULL }; + const char* buf; + Py_ssize_t buf_len; + gsize count; + GError* error = NULL; + GIOStatus status; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#:gobject.IOChannel.write", + kwlist, &buf, &buf_len)) + return NULL; + + pyglib_unblock_threads(); + status = g_io_channel_write_chars(self->channel, buf, buf_len, &count, &error); + pyglib_block_threads(); + if (pyglib_error_check(&error)) + return NULL; + + return PyInt_FromLong(count); +} + +static PyObject* +py_io_channel_write_lines(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "lines", NULL }; + char *buf; + Py_ssize_t buf_len; + gsize count; + GError* error = NULL; + GIOStatus status; + PyObject *iter, *value, *pylines; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:gobject.IOChannel.writelines", + kwlist, &pylines)) + return NULL; + + iter = PyObject_GetIter(pylines); + + while (1) { + value = PyIter_Next(iter); + if (PyErr_ExceptionMatches(PyExc_StopIteration)) { + PyErr_Clear(); + goto normal_exit; + } + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError, "gobject.IOChannel.writelines must" + " be sequence/iterator of strings"); + Py_DECREF(iter); + return NULL; + } + PyString_AsStringAndSize(value, &buf, &buf_len); + pyglib_unblock_threads(); + status = g_io_channel_write_chars(self->channel, buf, buf_len, &count, &error); + pyglib_unblock_threads(); + Py_DECREF(value); + if (pyglib_error_check(&error)) { + Py_DECREF(iter); + return NULL; + } + } +normal_exit: + Py_DECREF(iter); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +py_io_channel_flush(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { NULL }; + GError* error = NULL; + GIOStatus status; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.flush", + kwlist)) + return NULL; + + pyglib_unblock_threads(); + status = g_io_channel_flush(self->channel, &error); + pyglib_block_threads(); + if (pyglib_error_check(&error)) + return NULL; + + return PyInt_FromLong(status); +} + +static PyObject* +py_io_channel_set_flags(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "flags", NULL }; + GIOFlags flags; + GIOStatus status; + GError* error = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gobject.IOChannel.set_flags", + kwlist, &flags)) + return NULL; + + status = g_io_channel_set_flags(self->channel, flags, &error); + if (pyglib_error_check(&error)) + return NULL; + + return PyInt_FromLong(status); +} + +static PyObject* +py_io_channel_get_flags(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { NULL }; + GIOFlags flags; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.get_flags", + kwlist)) + return NULL; + + flags = g_io_channel_get_flags(self->channel); + return PyInt_FromLong(flags); +} + +static PyObject* +py_io_channel_get_buffer_condition(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { NULL }; + GIOCondition cond; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.get_buffer_condition", + kwlist)) + return NULL; + + cond = g_io_channel_get_buffer_condition(self->channel); + return PyInt_FromLong(cond); +} + +static PyObject* +py_io_channel_set_close_on_unref(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "do_close", NULL }; + PyObject *do_close; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:gobject.IOChannel.set_close_on_unref", + kwlist, &do_close)) + return NULL; + + g_io_channel_set_close_on_unref(self->channel, PyObject_IsTrue(do_close)); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +py_io_channel_get_close_on_unref(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + if (g_io_channel_get_close_on_unref(self->channel)) { + Py_INCREF(Py_True); + return Py_True; + } else { + Py_INCREF(Py_False); + return Py_False; + } +} + +typedef struct { + PyObject *callback; + PyObject *iochannel; + PyObject *user_data; +} PyGIOWatchData; + +static void +pyg_iowatch_data_free(PyGIOWatchData *data) +{ + Py_DECREF(data->callback); + Py_XDECREF(data->user_data); + Py_DECREF(data->iochannel); + g_free(data); +} + +static gboolean +pyg_iowatch_marshal(GIOChannel *source, + GIOCondition condition, + gpointer user_data) +{ + PyObject *ret; + gboolean res; + PyGIOWatchData *data = (PyGIOWatchData *) user_data; + PyGILState_STATE state; + + g_return_val_if_fail(user_data != NULL, FALSE); + g_return_val_if_fail(((PyGIOChannel *) data->iochannel)->channel == source, + FALSE); + + state = pyglib_gil_state_ensure(); + + if (data->user_data) + ret = PyObject_CallFunction(data->callback, "OiO", data->iochannel, + condition, data->user_data); + else + ret = PyObject_CallFunction(data->callback, "Oi", data->iochannel, + condition); + + if (!ret) { + PyErr_Print(); + res = FALSE; + } else { + res = PyObject_IsTrue(ret); + Py_DECREF(ret); + } + pyglib_gil_state_release(state); + + return res; +} + + + +static PyObject * +py_io_channel_add_watch(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "condition", "callback", "user_data", "priority", NULL }; + PyObject *callback, *user_data = NULL; + int priority = G_PRIORITY_DEFAULT, condition; + GIOChannel *iochannel = NULL; + guint handler_id; + PyGIOWatchData *data; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "iO|Oi:gobject.IOChannel.add_watch", + kwlist, &condition, &callback, + &user_data, &priority)) + return NULL; + + iochannel = ((PyGIOChannel *) self)->channel; + + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "second must be callable"); + return NULL; + } + + data = g_new(PyGIOWatchData, 1); + data->callback = callback; Py_INCREF(callback); + data->user_data = user_data; Py_XINCREF(user_data); + data->iochannel = self; Py_INCREF(self); + + handler_id = g_io_add_watch_full(((PyGIOChannel *) self)->channel, + priority, condition, + pyg_iowatch_marshal, data, + (GDestroyNotify) pyg_iowatch_data_free); + return PyLong_FromUnsignedLong(handler_id); +} + + +#ifdef G_OS_WIN32 + +static PyObject * +py_io_channel_win32_poll(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "fds", "timeout", NULL }; + GPollFD *pollfd; + PyObject *pyfds, *pyfd; + guint len, i; + gint timeout = -1; + gint result; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!|i:gobject.IOChannel.win32_poll", + kwlist, &PyList_Type, &pyfds, &timeout)) + return NULL; + + len = PyList_Size(pyfds); + pollfd = g_newa(GPollFD, len); + for (i = 0; i < len; ++i) { + pyfd = PyList_GET_ITEM(pyfds, i); + if (!PyObject_TypeCheck(pyfd, &PyGPollFD_Type)) { + PyErr_SetString(PyExc_TypeError, "'fds' must be a list of gobject.PollFD objects"); + return NULL; + } + pollfd[i] = ((PyGPollFD *) pyfd)->pollfd; + } + + result = g_io_channel_win32_poll(pollfd, len, timeout); + for (i = 0; i < len; ++i) { + pyfd = PyList_GET_ITEM(pyfds, i); + ((PyGPollFD *) pyfd)->pollfd = pollfd[i]; + } + return PyInt_FromLong(result); +} + +static PyObject * +py_io_channel_win32_make_pollfd(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "condition", NULL }; + int condition; + GPollFD pollfd; + PyGPollFD *pypollfd; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:gobject.IOChannel.win32_make_pollfd", + kwlist, &condition)) + return NULL; + + g_io_channel_win32_make_pollfd(((PyGIOChannel *) self)->channel, + condition, &pollfd); + pypollfd = PyObject_NEW(PyGPollFD, &PyGPollFD_Type); + pypollfd->pollfd = pollfd; + return (PyObject *) pypollfd; +} +#endif /* def G_OS_WIN32 */ + + +static PyObject* +py_io_channel_read_line(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "size", NULL }; + PyObject* ret_obj = NULL; + gsize length = 0, terminator_pos; + gchar *str_return = NULL; + GError *error = NULL; + gint size_hint = -1; + GIOStatus status; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:gobject.IOChannel.readline", kwlist, + &size_hint)) + return NULL; + + status = g_io_channel_read_line(self->channel, &str_return, &length, + &terminator_pos, &error); + if (pyglib_error_check(&error)) + return NULL; + ret_obj = PyString_FromStringAndSize(str_return, length); + g_free(str_return); + return ret_obj; +} + +static PyObject* +py_io_channel_read_lines(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "size", NULL }; + PyObject *line = NULL; + gsize length = 0, terminator_pos; + gchar *str_return = NULL; + GError *error = NULL; + gint size_hint = -1; + GIOStatus status = G_IO_STATUS_NORMAL; + PyObject *list; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:gobject.IOChannel.readlines", kwlist, + &size_hint)) + return NULL; + + list = PyList_New(0); + while (status == G_IO_STATUS_NORMAL) { + status = g_io_channel_read_line(self->channel, &str_return, &length, + &terminator_pos, &error); + if (pyglib_error_check(&error)) { + Py_DECREF(line); + return NULL; + } + line = PyString_FromStringAndSize(str_return, length); + g_free(str_return); + if (PyList_Append(list, line)) { + Py_DECREF(line); + Py_DECREF(list); + return NULL; + } + } + return list; +} + + +static PyObject* +py_io_channel_seek(PyGIOChannel* self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "offset", "whence", NULL }; + gint64 offset; + int whence = 0; + GIOStatus status; + GSeekType seek_type; + GError* error = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "L|i:gobject.IOChannel.seek", + kwlist, &offset, &whence)) + return NULL; + + switch (whence) + { + case 0: seek_type = G_SEEK_SET; break; + case 1: seek_type = G_SEEK_CUR; break; + case 2: seek_type = G_SEEK_END; break; + default: + PyErr_SetString(PyExc_ValueError, "invalid 'whence' value"); + return NULL; + } + + status = g_io_channel_seek_position(self->channel, offset, + seek_type, &error); + if (pyglib_error_check(&error)) + return NULL; + + return PyInt_FromLong(status); +} + +#if 0 // Not wrapped +void g_io_channel_set_line_term (GIOChannel *channel, + const gchar *line_term, + gint length); + +G_CONST_RETURN gchar* g_io_channel_get_line_term (GIOChannel *channel, + gint *length); + + + +GIOStatus g_io_channel_read_line_string (GIOChannel *channel, + GString *buffer, + gsize *terminator_pos, + GError **error); +GIOStatus g_io_channel_read_to_end (GIOChannel *channel, + gchar **str_return, + gsize *length, + GError **error); +GIOStatus g_io_channel_read_unichar (GIOChannel *channel, + gunichar *thechar, + GError **error); +GIOStatus g_io_channel_write_unichar (GIOChannel *channel, + gunichar thechar, + GError **error); +#endif // Not wrapped + +static PyMemberDef py_io_channel_members[] = { + { "softspace", T_INT, offsetof(PyGIOChannel, softspace), 0, NULL }, + { NULL, 0, 0, 0, NULL } +}; + +static PyMethodDef py_io_channel_methods[] = { + { "close", (PyCFunction)py_io_channel_shutdown, METH_KEYWORDS }, + { "flush", (PyCFunction)py_io_channel_flush, METH_KEYWORDS }, + { "set_encoding", (PyCFunction)py_io_channel_set_encoding, METH_KEYWORDS }, + { "get_encoding", (PyCFunction)py_io_channel_get_encoding, METH_KEYWORDS }, + { "set_buffered", (PyCFunction)py_io_channel_set_buffered, METH_KEYWORDS }, + { "get_buffered", (PyCFunction)py_io_channel_get_buffered, METH_KEYWORDS }, + { "set_buffer_size", (PyCFunction)py_io_channel_set_buffer_size, METH_KEYWORDS }, + { "get_buffer_size", (PyCFunction)py_io_channel_get_buffer_size, METH_KEYWORDS }, + { "read", (PyCFunction)py_io_channel_read_chars, METH_KEYWORDS }, + { "readline", (PyCFunction)py_io_channel_read_line, METH_KEYWORDS }, + { "readlines", (PyCFunction)py_io_channel_read_lines, METH_KEYWORDS }, + { "write", (PyCFunction)py_io_channel_write_chars, METH_KEYWORDS }, + { "writelines", (PyCFunction)py_io_channel_write_lines, METH_KEYWORDS }, + { "set_flags", (PyCFunction)py_io_channel_set_flags, METH_KEYWORDS }, + { "get_flags", (PyCFunction)py_io_channel_get_flags, METH_KEYWORDS }, + { "get_buffer_condition", (PyCFunction)py_io_channel_get_buffer_condition, METH_KEYWORDS }, + { "set_close_on_unref", (PyCFunction)py_io_channel_set_close_on_unref, METH_NOARGS }, + { "get_close_on_unref", (PyCFunction)py_io_channel_get_close_on_unref, METH_KEYWORDS }, + { "add_watch", (PyCFunction)py_io_channel_add_watch, METH_KEYWORDS }, + { "seek", (PyCFunction)py_io_channel_seek, METH_KEYWORDS }, +#ifdef G_OS_WIN32 + { "win32_make_pollfd", (PyCFunction)py_io_channel_win32_make_pollfd, METH_KEYWORDS }, + { "win32_poll", (PyCFunction)py_io_channel_win32_poll, METH_KEYWORDS|METH_STATIC }, +#endif + { NULL, NULL, 0 } +}; + + +static int +py_io_channel_init(PyGIOChannel *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "filedes", "filename", "mode", +#ifdef G_OS_WIN32 + "hwnd", +#endif + NULL }; + int fd = -1; + char *mode = "r", *filename = NULL; + GError *error = NULL; +#ifdef G_OS_WIN32 + guint hwnd = 0; +#endif + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iss" +#ifdef G_OS_WIN32 + "I" +#endif + ":gobject.IOChannel.__init__", + kwlist, &fd, &filename, &mode +#ifdef G_OS_WIN32 + , &hwnd +#endif + )) + return -1; + + if (fd != -1) + self->channel = g_io_channel_unix_new(fd); + else if (filename != NULL) { + self->channel = g_io_channel_new_file(filename, mode, &error); + if (pyglib_error_check(&error)) + return -1; + } +#ifdef G_OS_WIN32 + else if (hwnd != 0) { + self->channel = g_io_channel_win32_new_messages(hwnd); + } +#endif + else { +#ifdef G_OS_WIN32 + PyErr_SetString(PyExc_TypeError, "either a valid file descriptor, " + "file name, or window handle must be supplied"); +#else + PyErr_SetString(PyExc_TypeError, "either a valid file descriptor " + "or file name must be supplied"); +#endif + return -1; + } + return 0; +} + + +PyTypeObject PyGIOChannel_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "gobject.IOChannel", /* tp_name */ + sizeof(PyGIOChannel), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)py_io_channel_dealloc, /* tp_dealloc */ + (printfunc)0, /* tp_print */ + (getattrfunc)NULL, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + (cmpfunc)py_io_channel_compare, /* tp_compare */ + (reprfunc)0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)py_io_channel_hash, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)0, /* tp_str */ + (getattrofunc)0, /* tp_getattro */ + (setattrofunc)0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + NULL, /* Documentation string */ + (traverseproc)0, /* tp_traverse */ + (inquiry)0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)py_io_channel_get_iter,/* tp_iter */ + (iternextfunc)py_io_channel_next, /* tp_iternext */ + py_io_channel_methods, /* tp_methods */ + py_io_channel_members, /* tp_members */ + NULL, /* tp_getset */ + (PyTypeObject *)0, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)py_io_channel_init, /* tp_init */ + (allocfunc)0, /* tp_alloc */ + (newfunc)0, /* tp_new */ + 0, /* tp_free */ + (inquiry)0, /* tp_is_gc */ + (PyObject *)0, /* tp_bases */ +}; + +void +pyglib_iochannel_register_types(PyObject *d) +{ + PYGLIB_REGISTER_TYPE(d, PyGIOChannel_Type, "IOChannel"); +} diff --git a/glib/pygiochannel.h b/glib/pygiochannel.h new file mode 100644 index 0000000..35584b4 --- /dev/null +++ b/glib/pygiochannel.h @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#ifndef __PYG_IOCHANNEL_H__ +#define __PYG_IOCHANNEL_H__ + +extern PyTypeObject PyGIOChannel_Type; + +void pyglib_iochannel_register_types(PyObject *d); + +#endif /* __PYG_IOCHANNEL_H__ */ diff --git a/glib/pyglib-private.h b/glib/pyglib-private.h index fa8c6dd..4609e90 100644 --- a/glib/pyglib-private.h +++ b/glib/pyglib-private.h @@ -28,8 +28,10 @@ G_BEGIN_DECLS struct _PyGLib_Functions { - gboolean threads_enabled; - PyObject *gerror_exception; + gboolean threads_enabled; + PyObject *gerror_exception; + PyGLibThreadBlockFunc block_threads; + PyGLibThreadBlockFunc unblock_threads; }; #define PYGLIB_REGISTER_TYPE(d, type, name) \ diff --git a/glib/pyglib.c b/glib/pyglib.c index 3f7ebbd..a6d3c26 100644 --- a/glib/pyglib.c +++ b/glib/pyglib.c @@ -80,12 +80,16 @@ pyglib_init_internal(PyObject *api) gboolean pyglib_threads_enabled(void) { + g_return_val_if_fail (_PyGLib_API != NULL, FALSE); + return _PyGLib_API->threads_enabled; } PyGILState_STATE pyglib_gil_state_ensure(void) { + g_return_val_if_fail (_PyGLib_API != NULL, PyGILState_LOCKED); + if (!_PyGLib_API->threads_enabled) return PyGILState_LOCKED; @@ -95,6 +99,8 @@ pyglib_gil_state_ensure(void) void pyglib_gil_state_release(PyGILState_STATE state) { + g_return_if_fail (_PyGLib_API != NULL); + if (!_PyGLib_API->threads_enabled) return; @@ -116,6 +122,8 @@ pyglib_enable_threads(void) gboolean pyglib_enable_threads(void) { + g_return_val_if_fail (_PyGLib_API != NULL, FALSE); + if (_PyGLib_API->threads_enabled) return TRUE; @@ -142,6 +150,47 @@ pyglib_gil_state_release_py23 (int flag) PyGILState_Release(flag); } +/** + * pyglib_block_threads: + * + */ +void +pyglib_block_threads(void) +{ + g_return_if_fail (_PyGLib_API != NULL); + + if (_PyGLib_API->block_threads != NULL) + (* _PyGLib_API->block_threads)(); +} + +/** + * pyglib_unblock_threads: + * + */ +void +pyglib_unblock_threads(void) +{ + g_return_if_fail (_PyGLib_API != NULL); + if (_PyGLib_API->unblock_threads != NULL) + (* _PyGLib_API->unblock_threads)(); +} + +/** + * pyglib_set_thread_block_funcs: + * + * hooks to register handlers for getting GDK threads to cooperate + * with python threading + */ +void +pyglib_set_thread_block_funcs (PyGLibThreadBlockFunc block_threads_func, + PyGLibThreadBlockFunc unblock_threads_func) +{ + g_return_if_fail (_PyGLib_API != NULL); + + _PyGLib_API->block_threads = block_threads_func; + _PyGLib_API->unblock_threads = unblock_threads_func; +} + /** * pyglib_error_check: @@ -289,3 +338,50 @@ pyglib_main_context_new(GMainContext *context) self->context = g_main_context_ref(context); return (PyObject *)self; } + +gboolean +pyglib_handler_marshal(gpointer user_data) +{ + PyObject *tuple, *ret; + gboolean res; + PyGILState_STATE state; + + g_return_val_if_fail(user_data != NULL, FALSE); + + state = pyglib_gil_state_ensure(); + + tuple = (PyObject *)user_data; + ret = PyObject_CallObject(PyTuple_GetItem(tuple, 0), + PyTuple_GetItem(tuple, 1)); + if (!ret) { + PyErr_Print(); + res = FALSE; + } else { + res = PyObject_IsTrue(ret); + Py_DECREF(ret); + } + + pyglib_gil_state_release(state); + + return res; +} + +/** + * pyglib_destroy_notify: + * @user_data: a PyObject pointer. + * + * A function that can be used as a GDestroyNotify callback that will + * call Py_DECREF on the data. + */ +void +pyglib_destroy_notify(gpointer user_data) +{ + PyObject *obj = (PyObject *)user_data; + PyGILState_STATE state; + + g_return_if_fail (_PyGLib_API != NULL); + + state = pyglib_gil_state_ensure(); + Py_DECREF(obj); + pyglib_gil_state_release(state); +} diff --git a/glib/pyglib.h b/glib/pyglib.h index b2235d3..21da4d8 100644 --- a/glib/pyglib.h +++ b/glib/pyglib.h @@ -28,6 +28,8 @@ G_BEGIN_DECLS +typedef void (*PyGLibThreadBlockFunc) (void); + void pyglib_init(void); void pyglib_init_internal(PyObject *api); PyGILState_STATE pyglib_gil_state_ensure(void); @@ -37,6 +39,10 @@ gboolean pyglib_error_check(GError **error); gboolean pyglib_gerror_exception_check(GError **error); gboolean pyglib_threads_enabled(void); PyObject *pyglib_main_context_new(GMainContext *context); +gboolean pyglib_handler_marshal(gpointer user_data); +void pyglib_destroy_notify(gpointer user_data); +void pyglib_set_thread_block_funcs(PyGLibThreadBlockFunc block_threads_func, + PyGLibThreadBlockFunc unblock_threads_func); #define pyglib_begin_allow_threads \ G_STMT_START { \ diff --git a/glib/pygsource.c b/glib/pygsource.c new file mode 100644 index 0000000..1374c5d --- /dev/null +++ b/glib/pygsource.c @@ -0,0 +1,860 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pygtk- Python bindings for the GTK toolkit. + * Copyright (C) 1998-2003 James Henstridge + * Copyright (C) 2005 Oracle + * + * Author: Manish Singh + * + * pygsource.c: GSource wrapper + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include /* for PyMemberDef */ + +#include "pyglib.h" +#include "pyglib-private.h" +#include "pygmaincontext.h" +#include "pygsource.h" + +#define CHECK_DESTROYED(self, ret) G_STMT_START { \ + if ((self)->source == NULL) { \ + PyErr_SetString(PyExc_RuntimeError, "source is destroyed"); \ + return (ret); \ + } \ +} G_STMT_END + + +typedef struct { + PyObject_HEAD + GSource *source; + PyObject *inst_dict; + PyObject *weakreflist; + gboolean python_source; +} PyGSource; + +typedef struct +{ + GSource source; + PyObject *obj; +} PyGRealSource; + +static PyObject * +source_repr(PyGSource *self, const char *type) +{ + gchar buf[256], *desc; + + if (self->source) { + if (g_source_get_context(self->source)) + desc = "attached"; + else + desc = "unattached"; + } else { + desc = "destroyed"; + } + + if (type) + g_snprintf(buf, sizeof(buf), "<%s glib %s source at 0x%lx>", + desc, type, (long) self); + else + g_snprintf(buf, sizeof(buf), "<%s glib source at 0x%lx>", + desc, (long) self); + + return PyString_FromString(buf); +} + +static PyObject * +pyg_source_attach(PyGSource *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "context", NULL }; + PyGMainContext *py_context = NULL; + GMainContext *context = NULL; + guint id; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, + "|O!:attach", kwlist, + &PyGMainContext_Type, &py_context)) + return NULL; + + if (py_context) + context = py_context->context; + + CHECK_DESTROYED(self, NULL); + + if (self->python_source) { + PyGRealSource *pysource = (PyGRealSource *)self->source; + Py_INCREF(pysource->obj); + } + + id = g_source_attach(self->source, context); + return PyInt_FromLong(id); +} + +static PyObject * +pyg_source_destroy(PyGSource *self) +{ + CHECK_DESTROYED(self, NULL); + + if (self->python_source && self->source->context) { + PyGRealSource *pysource = (PyGRealSource *)self->source; + Py_DECREF(pysource->obj); + } + + g_source_destroy(self->source); + self->source = NULL; + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyg_source_set_callback(PyGSource *self, PyObject *args) +{ + PyObject *first, *callback, *cbargs = NULL, *data; + gint len; + + CHECK_DESTROYED(self, NULL); + + len = PyTuple_Size (args); + if (len < 1) { + PyErr_SetString(PyExc_TypeError, + "set_callback requires at least 1 argument"); + return NULL; + } + + first = PySequence_GetSlice(args, 0, 1); + if (!PyArg_ParseTuple(first, "O:set_callback", &callback)) { + Py_DECREF (first); + return NULL; + } + Py_DECREF(first); + + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "first argument not callable"); + return NULL; + } + + cbargs = PySequence_GetSlice(args, 1, len); + if (cbargs == NULL) + return NULL; + + data = Py_BuildValue("(ON)", callback, cbargs); + if (data == NULL) + return NULL; + + g_source_set_callback(self->source, + pyglib_handler_marshal, data, + pyglib_destroy_notify); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyg_source_get_context(PyGSource *self) +{ + GMainContext *context; + + CHECK_DESTROYED(self, NULL); + + context = g_source_get_context(self->source); + + if (context) { + return pyglib_main_context_new(context); + } else { + Py_INCREF(Py_None); + return Py_None; + } +} + +static PyObject * +pyg_source_add_poll(PyGSource *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "fd", NULL }; + PyGPollFD *fd; + + if (!self->python_source) { + PyErr_SetString(PyExc_TypeError, + "add_poll can only be used with sources " + "implemented in python"); + return NULL; + } + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!:add_poll", kwlist, + &PyGPollFD_Type, &fd)) + return NULL; + + CHECK_DESTROYED(self, NULL); + + g_source_add_poll(self->source, &fd->pollfd); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyg_source_remove_poll(PyGSource *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "fd", NULL }; + PyGPollFD *fd; + + if (!self->python_source) { + PyErr_SetString(PyExc_TypeError, + "remove_poll can only be used with sources " + "implemented in python"); + return NULL; + } + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!:remove_poll", kwlist, + &PyGPollFD_Type, &fd)) + return NULL; + + CHECK_DESTROYED(self, NULL); + + g_source_remove_poll(self->source, &fd->pollfd); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +pyg_source_get_current_time(PyGSource *self) +{ + GTimeVal timeval; + double ret; + + CHECK_DESTROYED(self, NULL); + + g_source_get_current_time(self->source, &timeval); + ret = (double)timeval.tv_sec + (double)timeval.tv_usec * 0.000001; + return PyFloat_FromDouble(ret); +} + +static PyMethodDef pyg_source_methods[] = { + { "attach", (PyCFunction)pyg_source_attach, METH_KEYWORDS }, + { "destroy", (PyCFunction)pyg_source_destroy, METH_NOARGS }, + { "set_callback", (PyCFunction)pyg_source_set_callback, METH_VARARGS }, + { "get_context", (PyCFunction)pyg_source_get_context, METH_NOARGS }, + { "add_poll", (PyCFunction)pyg_source_add_poll, METH_KEYWORDS }, + { "remove_poll", (PyCFunction)pyg_source_remove_poll, METH_KEYWORDS }, + { "get_current_time", (PyCFunction)pyg_source_get_current_time, METH_NOARGS }, + { NULL, NULL, 0 } +}; + +static PyObject * +pyg_source_get_dict(PyGSource *self, void *closure) +{ + if (self->inst_dict == NULL) { + self->inst_dict = PyDict_New(); + if (self->inst_dict == NULL) + return NULL; + } + + Py_INCREF(self->inst_dict); + return self->inst_dict; +} + +static PyObject * +pyg_source_get_priority(PyGSource *self, void *closure) +{ + CHECK_DESTROYED(self, NULL); + + return PyInt_FromLong(g_source_get_priority(self->source)); +} + +static int +pyg_source_set_priority(PyGSource *self, PyObject *value, void *closure) +{ + CHECK_DESTROYED(self, -1); + + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "cannot delete priority"); + return -1; + } + + if (!PyInt_Check(value)) { + PyErr_SetString(PyExc_TypeError, "type mismatch"); + return -1; + } + + g_source_set_priority(self->source, PyInt_AsLong(value)); + + return 0; +} + +static PyObject * +pyg_source_get_can_recurse(PyGSource *self, void *closure) +{ + CHECK_DESTROYED(self, NULL); + + return PyBool_FromLong(g_source_get_can_recurse(self->source)); +} + +static int +pyg_source_set_can_recurse(PyGSource *self, PyObject *value, void *closure) +{ + CHECK_DESTROYED(self, -1); + + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "cannot delete can_recurse"); + return -1; + } + + g_source_set_can_recurse(self->source, PyObject_IsTrue(value)); + + return 0; +} + +static PyObject * +pyg_source_get_id(PyGSource *self, void *closure) +{ + CHECK_DESTROYED(self, NULL); + + if (g_source_get_context(self->source) == NULL) { + PyErr_SetString(PyExc_RuntimeError, "source is not attached"); + return NULL; + } + + return PyInt_FromLong(g_source_get_id(self->source)); +} + +static PyGetSetDef pyg_source_getsets[] = { + { "__dict__", (getter)pyg_source_get_dict, (setter)0 }, + {"priority", (getter)pyg_source_get_priority, (setter)pyg_source_set_priority }, + {"can_recurse", (getter)pyg_source_get_can_recurse, (setter)pyg_source_set_can_recurse }, + {"id", (getter)pyg_source_get_id, (setter)0 }, + {NULL, 0, 0} +}; + +static PyObject * +pyg_source_repr(PyGSource *self) +{ + return source_repr(self, NULL); +} + +static int +pyg_source_traverse(PyGSource *self, visitproc visit, void *arg) +{ + int ret = 0; + + if (self->inst_dict) ret = visit(self->inst_dict, arg); + if (ret != 0) return ret; + + return 0; +} + +static int +pyg_source_clear(PyGSource *self) +{ + PyObject *tmp; + + tmp = self->inst_dict; + self->inst_dict = NULL; + Py_XDECREF(tmp); + + if (self->source) { + g_source_unref(self->source); + self->source = NULL; + } + + return 0; +} + +static void +pyg_source_dealloc(PyGSource *self) +{ + PyObject_ClearWeakRefs((PyObject *)self); + + PyObject_GC_UnTrack((PyObject *)self); + + pyg_source_clear(self); + + PyObject_GC_Del(self); +} + +static gboolean +pyg_source_prepare(GSource *source, gint *timeout) +{ + PyGRealSource *pysource = (PyGRealSource *)source; + PyObject *t; + gboolean ret = FALSE; + gboolean got_err = TRUE; + PyGILState_STATE state; + + state = pyglib_gil_state_ensure(); + + t = PyObject_CallMethod(pysource->obj, "prepare", NULL); + + if (t == NULL) { + goto bail; + } else if (!PyObject_IsTrue(t)) { + got_err = FALSE; + goto bail; + } else if (!PyTuple_Check(t)) { + PyErr_SetString(PyExc_TypeError, + "source prepare function must return a tuple or False"); + goto bail; + } else if (PyTuple_Size(t) != 2) { + PyErr_SetString(PyExc_TypeError, + "source prepare function return tuple must be exactly " + "2 elements long"); + goto bail; + } + + ret = PyObject_IsTrue(PyTuple_GET_ITEM(t, 0)); + *timeout = PyInt_AsLong(PyTuple_GET_ITEM(t, 1)); + + if (*timeout == -1 && PyErr_Occurred()) { + ret = FALSE; + goto bail; + } + + got_err = FALSE; + +bail: + if (got_err) + PyErr_Print(); + + Py_XDECREF(t); + + pyglib_gil_state_release(state); + + return ret; +} + +static gboolean +pyg_source_check(GSource *source) +{ + PyGRealSource *pysource = (PyGRealSource *)source; + PyObject *t; + gboolean ret; + PyGILState_STATE state; + + state = pyglib_gil_state_ensure(); + + t = PyObject_CallMethod(pysource->obj, "check", NULL); + + if (t == NULL) { + PyErr_Print(); + ret = FALSE; + } else { + ret = PyObject_IsTrue(t); + Py_DECREF(t); + } + + pyglib_gil_state_release(state); + + return ret; +} + +static gboolean +pyg_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) +{ + PyGRealSource *pysource = (PyGRealSource *)source; + PyObject *func, *args, *tuple, *t; + gboolean ret; + PyGILState_STATE state; + + state = pyglib_gil_state_ensure(); + + if (callback) { + tuple = user_data; + + func = PyTuple_GetItem(tuple, 0); + args = PyTuple_GetItem(tuple, 1); + } else { + func = Py_None; + args = Py_None; + } + + t = PyObject_CallMethod(pysource->obj, "dispatch", "OO", func, args); + + if (t == NULL) { + PyErr_Print(); + ret = FALSE; + } else { + ret = PyObject_IsTrue(t); + Py_DECREF(t); + } + + pyglib_gil_state_release(state); + + return ret; +} + +static void +pyg_source_finalize(GSource *source) +{ + PyGRealSource *pysource = (PyGRealSource *)source; + PyObject *func, *t; + PyGILState_STATE state; + + state = pyglib_gil_state_ensure(); + + func = PyObject_GetAttrString(pysource->obj, "finalize"); + if (func) { + t = PyObject_CallObject(func, NULL); + Py_DECREF(func); + + if (t == NULL) { + PyErr_Print(); + } else { + Py_DECREF(t); + } + } + + pyglib_gil_state_release(state); +} + +static GSourceFuncs pyg_source_funcs = +{ + pyg_source_prepare, + pyg_source_check, + pyg_source_dispatch, + pyg_source_finalize +}; + +static int +pyg_source_init(PyGSource *self, PyObject *args, PyObject *kwargs) +{ + PyGRealSource *pysource; + + self->source = g_source_new(&pyg_source_funcs, sizeof(PyGRealSource)); + + pysource = (PyGRealSource *)self->source; + pysource->obj = (PyObject*)self; + + self->inst_dict = NULL; + self->weakreflist = NULL; + + self->python_source = TRUE; + + return 0; +} + +static void +pyg_source_free(PyObject *op) +{ + PyObject_GC_Del(op); +} + +PyTypeObject PyGSource_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "gobject.Source", /* tp_name */ + sizeof(PyGSource), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pyg_source_dealloc, /* tp_dealloc */ + (printfunc)0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + (cmpfunc)0, /* tp_compare */ + (reprfunc)pyg_source_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)0, /* tp_str */ + (getattrofunc)0, /* tp_getattro */ + (setattrofunc)0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC, /* tp_flags */ + NULL, /* tp_doc */ + (traverseproc)pyg_source_traverse, /* tp_traverse */ + (inquiry)pyg_source_clear, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + offsetof(PyGSource, weakreflist), /* tp_weaklistoffset */ + (getiterfunc)0, /* tp_iter */ + (iternextfunc)0, /* tp_iternext */ + pyg_source_methods, /* tp_methods */ + 0, /* tp_members */ + pyg_source_getsets, /* tp_getset */ + (PyTypeObject *)0, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof(PyGSource, inst_dict), /* tp_dictoffset */ + (initproc)pyg_source_init, /* tp_init */ + (allocfunc)0, /* tp_alloc */ + (newfunc)0, /* tp_new */ + (freefunc)pyg_source_free, /* tp_free */ + (inquiry)0, /* tp_is_gc */ + (PyObject *)0, /* tp_bases */ +}; + +static PyObject * +pyg_idle_repr(PyGSource *self) +{ + return source_repr(self, "idle"); +} + +static int +pyg_idle_init(PyGSource *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "priority", NULL }; + gint priority = G_PRIORITY_DEFAULT_IDLE; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "|i:gobject.Idle.__init__", kwlist, + &priority)) + return -1; + + self->source = g_idle_source_new (); + + if (priority != G_PRIORITY_DEFAULT_IDLE) + g_source_set_priority(self->source, priority); + + self->inst_dict = NULL; + self->weakreflist = NULL; + + self->python_source = FALSE; + + return 0; +} + +PyTypeObject PyGIdle_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "gobject.Idle", /* tp_name */ + sizeof(PyGSource), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)0, /* tp_dealloc */ + (printfunc)0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + (cmpfunc)0, /* tp_compare */ + (reprfunc)pyg_idle_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)0, /* tp_str */ + (getattrofunc)0, /* tp_getattro */ + (setattrofunc)0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + NULL, /* tp_doc */ + (traverseproc)0, /* tp_traverse */ + (inquiry)0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)0, /* tp_iter */ + (iternextfunc)0, /* tp_iternext */ + NULL, /* tp_methods */ + NULL, /* tp_members */ + NULL, /* tp_getset */ + (PyTypeObject *)&PyGSource_Type, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)pyg_idle_init, /* tp_init */ + (allocfunc)0, /* tp_alloc */ + (newfunc)0, /* tp_new */ + (freefunc)0, /* tp_free */ + (inquiry)0, /* tp_is_gc */ + (PyObject *)0, /* tp_bases */ +}; + +static PyObject * +pyg_timeout_repr(PyGSource *self) +{ + return source_repr(self, "timeout"); +} + +static int +pyg_timeout_init(PyGSource *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "interval", "priority", NULL }; + gint priority = G_PRIORITY_DEFAULT; + guint interval; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "I|i:gobject.Timeout.__init__", kwlist, + &interval, &priority)) + return -1; + + self->source = g_timeout_source_new(interval); + + if (priority != G_PRIORITY_DEFAULT) + g_source_set_priority(self->source, priority); + + self->inst_dict = NULL; + self->weakreflist = NULL; + + self->python_source = FALSE; + + return 0; +} + +PyTypeObject PyGTimeout_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "gobject.Timeout", /* tp_name */ + sizeof(PyGSource), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)0, /* tp_dealloc */ + (printfunc)0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + (cmpfunc)0, /* tp_compare */ + (reprfunc)pyg_timeout_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)0, /* tp_str */ + (getattrofunc)0, /* tp_getattro */ + (setattrofunc)0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + NULL, /* tp_doc */ + (traverseproc)0, /* tp_traverse */ + (inquiry)0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)0, /* tp_iter */ + (iternextfunc)0, /* tp_iternext */ + NULL, /* tp_methods */ + NULL, /* tp_members */ + NULL, /* tp_getset */ + (PyTypeObject *)&PyGSource_Type, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)pyg_timeout_init, /* tp_init */ + (allocfunc)0, /* tp_alloc */ + (newfunc)0, /* tp_new */ + (freefunc)0, /* tp_free */ + (inquiry)0, /* tp_is_gc */ + (PyObject *)0, /* tp_bases */ +}; + +static PyMemberDef pyg_poll_fd_members[] = { + { "fd", T_INT, offsetof(PyGPollFD, pollfd.fd), RO }, + { "events", T_USHORT, offsetof(PyGPollFD, pollfd.events), RO }, + { "revents", T_USHORT, offsetof(PyGPollFD, pollfd.revents), RO }, + { NULL, 0, 0, 0 } +}; + +static void +pyg_poll_fd_dealloc(PyGPollFD *self) +{ + Py_XDECREF(self->fd_obj); + PyObject_DEL(self); +} + +static PyObject * +pyg_poll_fd_repr(PyGPollFD *self) +{ + return PyString_FromFormat("", + self->pollfd.fd, self->pollfd.events, + (long)self); +} + +static int +pyg_poll_fd_init(PyGPollFD *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "fd", "events", NULL }; + PyObject *o; + gint fd; + gushort events; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "OH:gobject.PollFD.__init__", kwlist, + &o, &events)) + return -1; + + fd = PyObject_AsFileDescriptor(o); + if (fd == -1) + return -1; + + self->pollfd.fd = fd; + self->pollfd.events = events; + self->pollfd.revents = 0; + + Py_INCREF(o); + self->fd_obj = o; + + return 0; +} + +PyTypeObject PyGPollFD_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "gobject.PollFD", /* tp_name */ + sizeof(PyGPollFD), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pyg_poll_fd_dealloc, /* tp_dealloc */ + (printfunc)0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + (cmpfunc)0, /* tp_compare */ + (reprfunc)pyg_poll_fd_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)0, /* tp_str */ + (getattrofunc)0, /* tp_getattro */ + (setattrofunc)0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + NULL, /* tp_doc */ + (traverseproc)0, /* tp_traverse */ + (inquiry)0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)0, /* tp_iter */ + (iternextfunc)0, /* tp_iternext */ + 0, /* tp_methods */ + pyg_poll_fd_members, /* tp_members */ + 0, /* tp_getset */ + (PyTypeObject *)0, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)pyg_poll_fd_init, /* tp_init */ + (allocfunc)0, /* tp_alloc */ + (newfunc)0, /* tp_new */ + (freefunc)0, /* tp_free */ + (inquiry)0, /* tp_is_gc */ + (PyObject *)0, /* tp_bases */ +}; + +void +pyglib_source_register_types(PyObject *d) +{ + PYGLIB_REGISTER_TYPE(d, PyGSource_Type, "Source"); + PYGLIB_REGISTER_TYPE(d, PyGIdle_Type, "Idle"); + PYGLIB_REGISTER_TYPE(d, PyGTimeout_Type, "Timeout"); + PYGLIB_REGISTER_TYPE(d, PyGPollFD_Type, "PollFD"); +} diff --git a/glib/pygsource.h b/glib/pygsource.h new file mode 100644 index 0000000..bbfeee5 --- /dev/null +++ b/glib/pygsource.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * pyglib - Python bindings for GLib toolkit. + * Copyright (C) 1998-2003 James Henstridge + * 2004-2008 Johan Dahlin + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#ifndef __PYG_SOURCE_H__ +#define __PYG_SOURCE_H__ + +extern PyTypeObject PyGSource_Type; +extern PyTypeObject PyGIdle_Type; +extern PyTypeObject PyGTimeout_Type; +extern PyTypeObject PyGPollFD_Type; + +typedef struct +{ + PyObject_HEAD + GPollFD pollfd; + PyObject *fd_obj; +} PyGPollFD; + +void pyglib_source_register_types(PyObject *d); + +#endif /* __PYG_SOURCE_H__ */ diff --git a/glib/pygspawn.c b/glib/pygspawn.c index 08c40aa..7f35f58 100644 --- a/glib/pygspawn.c +++ b/glib/pygspawn.c @@ -290,7 +290,7 @@ pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs) } void -pyg_spawn_register_types(PyObject *d) +pyglib_spawn_register_types(PyObject *d) { PyGPid_Type.tp_base = &PyInt_Type; PYGLIB_REGISTER_TYPE(d, PyGPid_Type, "Pid"); diff --git a/glib/pygspawn.h b/glib/pygspawn.h index e283b85..05dca15 100644 --- a/glib/pygspawn.h +++ b/glib/pygspawn.h @@ -23,7 +23,7 @@ #define __PYG_PID_H__ PyObject * pyg_pid_new(GPid pid); -void pyg_spawn_register_types(PyObject *d); +void pyglib_spawn_register_types(PyObject *d); PyObject * pyglib_spawn_async(PyObject *self, PyObject *args, PyObject *kwargs); diff --git a/gobject/Makefile.am b/gobject/Makefile.am index dfd0f50..74c2e4c 100644 --- a/gobject/Makefile.am +++ b/gobject/Makefile.am @@ -53,8 +53,6 @@ _gobject_la_SOURCES = \ pygobject-private.h \ pygparamspec.c \ pygpointer.c \ - pygiochannel.c \ - pygsource.c \ pygtype.c \ pygoptioncontext.c \ pygoptiongroup.c diff --git a/gobject/__init__.py b/gobject/__init__.py index 19bdd0c..eba3eaf 100644 --- a/gobject/__init__.py +++ b/gobject/__init__.py @@ -32,7 +32,9 @@ from glib import spawn_async, idle_add, timeout_add, timeout_add_seconds, \ get_current_time, filename_display_name, filename_display_basename, \ filename_from_utf8, get_application_name, set_application_name, \ get_prgname, set_prgname, main_depth, Pid, GError, glib_version, \ - MainLoop, MainContext, main_context_default + MainLoop, MainContext, main_context_default, IOChannel, Source, Idle, \ + Timeout, PollFD + from gobject.constants import * from _gobject import * _PyGObject_API = _gobject._PyGObject_API diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index 5af2c38..a5bf3aa 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -79,6 +79,8 @@ pyg_set_thread_block_funcs (PyGThreadBlockFunc block_threads_func, pygobject_api_functions.block_threads = block_threads_func; pygobject_api_functions.unblock_threads = unblock_threads_func; + pyglib_set_thread_block_funcs(block_threads_func, + unblock_threads_func); } static void @@ -2753,13 +2755,6 @@ init_gobject(void) PyGFlags_Type.tp_base = &PyInt_Type; REGISTER_GTYPE(d, PyGFlags_Type, "GFlags", G_TYPE_FLAGS); - REGISTER_TYPE(d, PyGIOChannel_Type, "IOChannel"); - - REGISTER_TYPE(d, PyGSource_Type, "Source"); - REGISTER_TYPE(d, PyGIdle_Type, "Idle"); - REGISTER_TYPE(d, PyGTimeout_Type, "Timeout"); - REGISTER_TYPE(d, PyGPollFD_Type, "PollFD"); - PyType_Ready(&PyGObjectWeakRef_Type); PyDict_SetItemString(d, "GObjectWeakRef", (PyObject *) &PyGObjectWeakRef_Type); @@ -2781,7 +2776,6 @@ init_gobject(void) o=PyCObject_FromVoidPtr(&pygobject_api_functions,NULL)); Py_DECREF(o); - /* features */ features = PyDict_New(); #ifdef HAVE_FFI_H diff --git a/gobject/pygiochannel.c b/gobject/pygiochannel.c deleted file mode 100644 index 34ef837..0000000 --- a/gobject/pygiochannel.c +++ /dev/null @@ -1,812 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4 -*- */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include "pygobject-private.h" -#include "pythread.h" -#include /* for PyMemberDef */ - - -typedef struct { - PyObject_HEAD - GIOChannel *channel; - int softspace; /* to make print >> chan, "foo" ... work */ -} PyGIOChannel; - -static PyObject* -py_io_channel_next(PyGIOChannel *self) -{ - PyObject* ret_obj = NULL; - gsize length = 0, terminator_pos; - gchar *str_return = NULL; - GError *error = NULL; - GIOStatus status; - - status = g_io_channel_read_line(self->channel, &str_return, &length, - &terminator_pos, &error); - if (pyg_error_check(&error)) - return NULL; - - if (status == G_IO_STATUS_EOF) { - PyErr_SetString(PyExc_StopIteration, "EOF"); - return NULL; - } - - ret_obj = PyString_FromStringAndSize(str_return, length); - g_free(str_return); - return ret_obj; - -} - -static int -py_io_channel_compare(PyGIOChannel *self, PyGIOChannel *v) -{ - if (self->channel == v->channel) return 0; - if (self->channel > v->channel) return -1; - return 1; -} - -static PyObject* -py_io_channel_get_iter(PyObject *self) -{ - Py_INCREF(self); - return self; -} - -static long -py_io_channel_hash(PyGIOChannel *self) -{ - return (long) self->channel; -} - -static void -py_io_channel_dealloc(PyGIOChannel *self) -{ - if (self->channel) - g_io_channel_unref(self->channel); - PyObject_DEL(self); -} - -static PyObject* -py_io_channel_shutdown(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "flush", NULL }; - GIOStatus ret; - PyObject* flush = Py_True; - GError* error = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:gobject.IOChannel.shutdown", kwlist, &flush)) - return NULL; - - ret = g_io_channel_shutdown(self->channel, PyObject_IsTrue(flush), &error); - if (pyg_error_check(&error)) - return NULL; - - return PyInt_FromLong(ret); -} - -/* character encoding conversion involved functions. - */ - -static PyObject* -py_io_channel_set_buffer_size(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "size", NULL }; - int size; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gobject.IOChannel.set_buffer_size", kwlist, &size)) - return NULL; - - g_io_channel_set_buffer_size(self->channel, size); - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* -py_io_channel_get_buffer_size(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { NULL }; - int size; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gobject.IOChannel.get_buffer_size", kwlist)) - return NULL; - - size = g_io_channel_get_buffer_size(self->channel); - - return PyInt_FromLong(size); -} - -static PyObject* -py_io_channel_set_buffered(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "buffered", NULL }; - int buffered; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gobject.IOChannel.set_buffered", kwlist, &buffered)) - return NULL; - - g_io_channel_set_buffered(self->channel, buffered); - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* -py_io_channel_get_buffered(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { NULL }; - int buffered; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.get_buffered", kwlist)) - return NULL; - - buffered = g_io_channel_get_buffered(self->channel); - - return PyInt_FromLong(buffered); -} - -static PyObject* -py_io_channel_set_encoding(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "encoding", NULL }; - const char* encoding; - GError* error = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z:gobject.IOChannel.set_encoding", kwlist, &encoding)) - return NULL; - - g_io_channel_set_encoding(self->channel, encoding, &error); - if (pyg_error_check(&error)) - return NULL; - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* -py_io_channel_get_encoding(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { NULL }; - const char* encoding; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.get_encoding", kwlist)) - return NULL; - - encoding = g_io_channel_get_encoding(self->channel); - - if (encoding == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - - return PyString_FromString(encoding); -} - -#define CHUNK_SIZE (8 * 1024) - -static PyObject* -py_io_channel_read_chars(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "max_count", NULL }; - int max_count = -1; - PyObject* ret_obj = NULL; - gsize total_read = 0; - GError* error = NULL; - GIOStatus status = G_IO_STATUS_NORMAL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:gobject.IOChannel.read", kwlist, &max_count)) - return NULL; - - if (max_count == 0) - return PyString_FromString(""); - - while (status == G_IO_STATUS_NORMAL - && (max_count == -1 || total_read < max_count)) { - gsize single_read; - char* buf; - gsize buf_size; - - if (max_count == -1) - buf_size = CHUNK_SIZE; - else { - buf_size = max_count - total_read; - if (buf_size > CHUNK_SIZE) - buf_size = CHUNK_SIZE; - } - - if ( ret_obj == NULL ) { - ret_obj = PyString_FromStringAndSize((char *)NULL, buf_size); - if (ret_obj == NULL) - goto failure; - } - else if (buf_size + total_read > PyString_GET_SIZE(ret_obj)) { - if (_PyString_Resize(&ret_obj, buf_size + total_read) == -1) - goto failure; - } - - buf = PyString_AS_STRING(ret_obj) + total_read; - - pyg_unblock_threads(); - status = g_io_channel_read_chars(self->channel, buf, buf_size, - &single_read, &error); - pyg_block_threads(); - if (pyg_error_check(&error)) - goto failure; - - total_read += single_read; - } - - if ( total_read != PyString_GET_SIZE(ret_obj) ) { - if (_PyString_Resize(&ret_obj, total_read) == -1) - goto failure; - } - return ret_obj; - - failure: - Py_XDECREF(ret_obj); - return NULL; -} - -static PyObject* -py_io_channel_write_chars(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "buf", NULL }; - const char* buf; - Py_ssize_t buf_len; - gsize count; - GError* error = NULL; - GIOStatus status; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#:gobject.IOChannel.write", - kwlist, &buf, &buf_len)) - return NULL; - - pyg_unblock_threads(); - status = g_io_channel_write_chars(self->channel, buf, buf_len, &count, &error); - pyg_block_threads(); - if (pyg_error_check(&error)) - return NULL; - - return PyInt_FromLong(count); -} - -static PyObject* -py_io_channel_write_lines(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "lines", NULL }; - char *buf; - Py_ssize_t buf_len; - gsize count; - GError* error = NULL; - GIOStatus status; - PyObject *iter, *value, *pylines; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:gobject.IOChannel.writelines", - kwlist, &pylines)) - return NULL; - - iter = PyObject_GetIter(pylines); - - while (1) { - value = PyIter_Next(iter); - if (PyErr_ExceptionMatches(PyExc_StopIteration)) { - PyErr_Clear(); - goto normal_exit; - } - if (!PyString_Check(value)) { - PyErr_SetString(PyExc_TypeError, "gobject.IOChannel.writelines must" - " be sequence/iterator of strings"); - Py_DECREF(iter); - return NULL; - } - PyString_AsStringAndSize(value, &buf, &buf_len); - pyg_unblock_threads(); - status = g_io_channel_write_chars(self->channel, buf, buf_len, &count, &error); - pyg_unblock_threads(); - Py_DECREF(value); - if (pyg_error_check(&error)) { - Py_DECREF(iter); - return NULL; - } - } -normal_exit: - Py_DECREF(iter); - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* -py_io_channel_flush(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { NULL }; - GError* error = NULL; - GIOStatus status; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.flush", - kwlist)) - return NULL; - - pyg_unblock_threads(); - status = g_io_channel_flush(self->channel, &error); - pyg_block_threads(); - if (pyg_error_check(&error)) - return NULL; - - return PyInt_FromLong(status); -} - -static PyObject* -py_io_channel_set_flags(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "flags", NULL }; - GIOFlags flags; - GIOStatus status; - GError* error = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gobject.IOChannel.set_flags", - kwlist, &flags)) - return NULL; - - status = g_io_channel_set_flags(self->channel, flags, &error); - if (pyg_error_check(&error)) - return NULL; - - return PyInt_FromLong(status); -} - -static PyObject* -py_io_channel_get_flags(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { NULL }; - GIOFlags flags; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.get_flags", - kwlist)) - return NULL; - - flags = g_io_channel_get_flags(self->channel); - return PyInt_FromLong(flags); -} - -static PyObject* -py_io_channel_get_buffer_condition(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { NULL }; - GIOCondition cond; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gobject.IOChannel.get_buffer_condition", - kwlist)) - return NULL; - - cond = g_io_channel_get_buffer_condition(self->channel); - return PyInt_FromLong(cond); -} - -static PyObject* -py_io_channel_set_close_on_unref(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "do_close", NULL }; - PyObject *do_close; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:gobject.IOChannel.set_close_on_unref", - kwlist, &do_close)) - return NULL; - - g_io_channel_set_close_on_unref(self->channel, PyObject_IsTrue(do_close)); - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* -py_io_channel_get_close_on_unref(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - if (g_io_channel_get_close_on_unref(self->channel)) { - Py_INCREF(Py_True); - return Py_True; - } else { - Py_INCREF(Py_False); - return Py_False; - } -} - -typedef struct { - PyObject *callback; - PyObject *iochannel; - PyObject *user_data; -} PyGIOWatchData; - -static void -pyg_iowatch_data_free(PyGIOWatchData *data) -{ - Py_DECREF(data->callback); - Py_XDECREF(data->user_data); - Py_DECREF(data->iochannel); - g_free(data); -} - -static gboolean -pyg_iowatch_marshal(GIOChannel *source, - GIOCondition condition, - gpointer user_data) -{ - PyObject *ret; - gboolean res; - PyGIOWatchData *data = (PyGIOWatchData *) user_data; - PyGILState_STATE state; - - g_return_val_if_fail(user_data != NULL, FALSE); - g_return_val_if_fail(((PyGIOChannel *) data->iochannel)->channel == source, - FALSE); - - state = pyglib_gil_state_ensure(); - - if (data->user_data) - ret = PyObject_CallFunction(data->callback, "OiO", data->iochannel, - condition, data->user_data); - else - ret = PyObject_CallFunction(data->callback, "Oi", data->iochannel, - condition); - - if (!ret) { - PyErr_Print(); - res = FALSE; - } else { - res = PyObject_IsTrue(ret); - Py_DECREF(ret); - } - pyglib_gil_state_release(state); - - return res; -} - - - -static PyObject * -py_io_channel_add_watch(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "condition", "callback", "user_data", "priority", NULL }; - PyObject *callback, *user_data = NULL; - int priority = G_PRIORITY_DEFAULT, condition; - GIOChannel *iochannel = NULL; - guint handler_id; - PyGIOWatchData *data; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "iO|Oi:gobject.IOChannel.add_watch", - kwlist, &condition, &callback, - &user_data, &priority)) - return NULL; - - iochannel = ((PyGIOChannel *) self)->channel; - - if (!PyCallable_Check(callback)) { - PyErr_SetString(PyExc_TypeError, "second must be callable"); - return NULL; - } - - data = g_new(PyGIOWatchData, 1); - data->callback = callback; Py_INCREF(callback); - data->user_data = user_data; Py_XINCREF(user_data); - data->iochannel = self; Py_INCREF(self); - - handler_id = g_io_add_watch_full(((PyGIOChannel *) self)->channel, - priority, condition, - pyg_iowatch_marshal, data, - (GDestroyNotify) pyg_iowatch_data_free); - return PyLong_FromUnsignedLong(handler_id); -} - - -#ifdef G_OS_WIN32 - -static PyObject * -py_io_channel_win32_poll(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "fds", "timeout", NULL }; - GPollFD *pollfd; - PyObject *pyfds, *pyfd; - guint len, i; - gint timeout = -1; - gint result; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O!|i:gobject.IOChannel.win32_poll", - kwlist, &PyList_Type, &pyfds, &timeout)) - return NULL; - - len = PyList_Size(pyfds); - pollfd = g_newa(GPollFD, len); - for (i = 0; i < len; ++i) { - pyfd = PyList_GET_ITEM(pyfds, i); - if (!PyObject_TypeCheck(pyfd, &PyGPollFD_Type)) { - PyErr_SetString(PyExc_TypeError, "'fds' must be a list of gobject.PollFD objects"); - return NULL; - } - pollfd[i] = ((PyGPollFD *) pyfd)->pollfd; - } - - result = g_io_channel_win32_poll(pollfd, len, timeout); - for (i = 0; i < len; ++i) { - pyfd = PyList_GET_ITEM(pyfds, i); - ((PyGPollFD *) pyfd)->pollfd = pollfd[i]; - } - return PyInt_FromLong(result); -} - -static PyObject * -py_io_channel_win32_make_pollfd(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "condition", NULL }; - int condition; - GPollFD pollfd; - PyGPollFD *pypollfd; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:gobject.IOChannel.win32_make_pollfd", - kwlist, &condition)) - return NULL; - - g_io_channel_win32_make_pollfd(((PyGIOChannel *) self)->channel, - condition, &pollfd); - pypollfd = PyObject_NEW(PyGPollFD, &PyGPollFD_Type); - pypollfd->pollfd = pollfd; - return (PyObject *) pypollfd; -} -#endif /* def G_OS_WIN32 */ - - -static PyObject* -py_io_channel_read_line(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "size", NULL }; - PyObject* ret_obj = NULL; - gsize length = 0, terminator_pos; - gchar *str_return = NULL; - GError *error = NULL; - gint size_hint = -1; - GIOStatus status; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:gobject.IOChannel.readline", kwlist, - &size_hint)) - return NULL; - - status = g_io_channel_read_line(self->channel, &str_return, &length, - &terminator_pos, &error); - if (pyg_error_check(&error)) - return NULL; - ret_obj = PyString_FromStringAndSize(str_return, length); - g_free(str_return); - return ret_obj; -} - -static PyObject* -py_io_channel_read_lines(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "size", NULL }; - PyObject *line = NULL; - gsize length = 0, terminator_pos; - gchar *str_return = NULL; - GError *error = NULL; - gint size_hint = -1; - GIOStatus status = G_IO_STATUS_NORMAL; - PyObject *list; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:gobject.IOChannel.readlines", kwlist, - &size_hint)) - return NULL; - - list = PyList_New(0); - while (status == G_IO_STATUS_NORMAL) { - status = g_io_channel_read_line(self->channel, &str_return, &length, - &terminator_pos, &error); - if (pyg_error_check(&error)) { - Py_DECREF(line); - return NULL; - } - line = PyString_FromStringAndSize(str_return, length); - g_free(str_return); - if (PyList_Append(list, line)) { - Py_DECREF(line); - Py_DECREF(list); - return NULL; - } - } - return list; -} - - -static PyObject* -py_io_channel_seek(PyGIOChannel* self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "offset", "whence", NULL }; - gint64 offset; - int whence = 0; - GIOStatus status; - GSeekType seek_type; - GError* error = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "L|i:gobject.IOChannel.seek", - kwlist, &offset, &whence)) - return NULL; - - switch (whence) - { - case 0: seek_type = G_SEEK_SET; break; - case 1: seek_type = G_SEEK_CUR; break; - case 2: seek_type = G_SEEK_END; break; - default: - PyErr_SetString(PyExc_ValueError, "invalid 'whence' value"); - return NULL; - } - - status = g_io_channel_seek_position(self->channel, offset, - seek_type, &error); - if (pyg_error_check(&error)) - return NULL; - - return PyInt_FromLong(status); -} - -#if 0 // Not wrapped -void g_io_channel_set_line_term (GIOChannel *channel, - const gchar *line_term, - gint length); - -G_CONST_RETURN gchar* g_io_channel_get_line_term (GIOChannel *channel, - gint *length); - - - -GIOStatus g_io_channel_read_line_string (GIOChannel *channel, - GString *buffer, - gsize *terminator_pos, - GError **error); -GIOStatus g_io_channel_read_to_end (GIOChannel *channel, - gchar **str_return, - gsize *length, - GError **error); -GIOStatus g_io_channel_read_unichar (GIOChannel *channel, - gunichar *thechar, - GError **error); -GIOStatus g_io_channel_write_unichar (GIOChannel *channel, - gunichar thechar, - GError **error); -#endif // Not wrapped - -static PyMemberDef py_io_channel_members[] = { - { "softspace", T_INT, offsetof(PyGIOChannel, softspace), 0, NULL }, - { NULL, 0, 0, 0, NULL } -}; - -static PyMethodDef py_io_channel_methods[] = { - { "close", (PyCFunction)py_io_channel_shutdown, METH_KEYWORDS }, - { "flush", (PyCFunction)py_io_channel_flush, METH_KEYWORDS }, - { "set_encoding", (PyCFunction)py_io_channel_set_encoding, METH_KEYWORDS }, - { "get_encoding", (PyCFunction)py_io_channel_get_encoding, METH_KEYWORDS }, - { "set_buffered", (PyCFunction)py_io_channel_set_buffered, METH_KEYWORDS }, - { "get_buffered", (PyCFunction)py_io_channel_get_buffered, METH_KEYWORDS }, - { "set_buffer_size", (PyCFunction)py_io_channel_set_buffer_size, METH_KEYWORDS }, - { "get_buffer_size", (PyCFunction)py_io_channel_get_buffer_size, METH_KEYWORDS }, - { "read", (PyCFunction)py_io_channel_read_chars, METH_KEYWORDS }, - { "readline", (PyCFunction)py_io_channel_read_line, METH_KEYWORDS }, - { "readlines", (PyCFunction)py_io_channel_read_lines, METH_KEYWORDS }, - { "write", (PyCFunction)py_io_channel_write_chars, METH_KEYWORDS }, - { "writelines", (PyCFunction)py_io_channel_write_lines, METH_KEYWORDS }, - { "set_flags", (PyCFunction)py_io_channel_set_flags, METH_KEYWORDS }, - { "get_flags", (PyCFunction)py_io_channel_get_flags, METH_KEYWORDS }, - { "get_buffer_condition", (PyCFunction)py_io_channel_get_buffer_condition, METH_KEYWORDS }, - { "set_close_on_unref", (PyCFunction)py_io_channel_set_close_on_unref, METH_NOARGS }, - { "get_close_on_unref", (PyCFunction)py_io_channel_get_close_on_unref, METH_KEYWORDS }, - { "add_watch", (PyCFunction)py_io_channel_add_watch, METH_KEYWORDS }, - { "seek", (PyCFunction)py_io_channel_seek, METH_KEYWORDS }, -#ifdef G_OS_WIN32 - { "win32_make_pollfd", (PyCFunction)py_io_channel_win32_make_pollfd, METH_KEYWORDS }, - { "win32_poll", (PyCFunction)py_io_channel_win32_poll, METH_KEYWORDS|METH_STATIC }, -#endif - { NULL, NULL, 0 } -}; - - -static int -py_io_channel_init(PyGIOChannel *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "filedes", "filename", "mode", -#ifdef G_OS_WIN32 - "hwnd", -#endif - NULL }; - int fd = -1; - char *mode = "r", *filename = NULL; - GError *error = NULL; -#ifdef G_OS_WIN32 - guint hwnd = 0; -#endif - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iss" -#ifdef G_OS_WIN32 - "I" -#endif - ":gobject.IOChannel.__init__", - kwlist, &fd, &filename, &mode -#ifdef G_OS_WIN32 - , &hwnd -#endif - )) - return -1; - - if (fd != -1) - self->channel = g_io_channel_unix_new(fd); - else if (filename != NULL) { - self->channel = g_io_channel_new_file(filename, mode, &error); - if (pyg_error_check(&error)) - return -1; - } -#ifdef G_OS_WIN32 - else if (hwnd != 0) { - self->channel = g_io_channel_win32_new_messages(hwnd); - } -#endif - else { -#ifdef G_OS_WIN32 - PyErr_SetString(PyExc_TypeError, "either a valid file descriptor, " - "file name, or window handle must be supplied"); -#else - PyErr_SetString(PyExc_TypeError, "either a valid file descriptor " - "or file name must be supplied"); -#endif - return -1; - } - return 0; -} - - -PyTypeObject PyGIOChannel_Type = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - "gobject.IOChannel", /* tp_name */ - sizeof(PyGIOChannel), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)py_io_channel_dealloc, /* tp_dealloc */ - (printfunc)0, /* tp_print */ - (getattrfunc)NULL, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ - (cmpfunc)py_io_channel_compare, /* tp_compare */ - (reprfunc)0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)py_io_channel_hash, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)0, /* tp_str */ - (getattrofunc)0, /* tp_getattro */ - (setattrofunc)0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - NULL, /* Documentation string */ - (traverseproc)0, /* tp_traverse */ - (inquiry)0, /* tp_clear */ - (richcmpfunc)0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)py_io_channel_get_iter,/* tp_iter */ - (iternextfunc)py_io_channel_next, /* tp_iternext */ - py_io_channel_methods, /* tp_methods */ - py_io_channel_members, /* tp_members */ - NULL, /* tp_getset */ - (PyTypeObject *)0, /* tp_base */ - (PyObject *)0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)py_io_channel_init, /* tp_init */ - (allocfunc)0, /* tp_alloc */ - (newfunc)0, /* tp_new */ - 0, /* tp_free */ - (inquiry)0, /* tp_is_gc */ - (PyObject *)0, /* tp_bases */ -}; - diff --git a/gobject/pygobject-private.h b/gobject/pygobject-private.h index 5b71ed5..1b2255b 100644 --- a/gobject/pygobject-private.h +++ b/gobject/pygobject-private.h @@ -145,6 +145,13 @@ extern PyTypeObject PyGInterface_Type; extern PyTypeObject PyGProps_Type; extern PyTypeObject PyGPropsDescr_Type; extern PyTypeObject PyGPropsIter_Type; + + /* Data that belongs to the GObject instance, not the Python wrapper */ +struct _PyGObjectData { + PyTypeObject *type; /* wrapper type for this instance */ + GSList *closures; +}; + void pygobject_register_class (PyObject *dict, const gchar *type_name, GType gtype, PyTypeObject *type, @@ -236,28 +243,6 @@ PyTypeObject *_PyGMainContext_Type; extern PyTypeObject PyGParamSpec_Type; PyObject * pyg_param_spec_new (GParamSpec *pspec); -/* pygiochannel.c */ -extern PyTypeObject PyGIOChannel_Type; - -/* pygsource.c */ -extern PyTypeObject PyGSource_Type; -extern PyTypeObject PyGIdle_Type; -extern PyTypeObject PyGTimeout_Type; -extern PyTypeObject PyGPollFD_Type; - -typedef struct -{ - PyObject_HEAD - GPollFD pollfd; - PyObject *fd_obj; -} PyGPollFD; - - /* Data that belongs to the GObject instance, not the Python wrapper */ -struct _PyGObjectData { - PyTypeObject *type; /* wrapper type for this instance */ - GSList *closures; -}; - /* pygoption.c */ extern PyTypeObject PyGOptionContext_Type; extern PyTypeObject PyGOptionGroup_Type; diff --git a/gobject/pygsource.c b/gobject/pygsource.c deleted file mode 100644 index ae667dc..0000000 --- a/gobject/pygsource.c +++ /dev/null @@ -1,847 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4 -*- - * pygtk- Python bindings for the GTK toolkit. - * Copyright (C) 1998-2003 James Henstridge - * Copyright (C) 2005 Oracle - * - * Author: Manish Singh - * - * pygsource.c: GSource wrapper - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "pygobject-private.h" -#include "pythread.h" -#include -#include - - -#define CHECK_DESTROYED(self, ret) G_STMT_START { \ - if ((self)->source == NULL) { \ - PyErr_SetString(PyExc_RuntimeError, "source is destroyed"); \ - return (ret); \ - } \ -} G_STMT_END - - -typedef struct { - PyObject_HEAD - GSource *source; - PyObject *inst_dict; - PyObject *weakreflist; - gboolean python_source; -} PyGSource; - -typedef struct -{ - GSource source; - PyObject *obj; -} PyGRealSource; - -static PyObject * -source_repr(PyGSource *self, const char *type) -{ - gchar buf[256], *desc; - - if (self->source) { - if (g_source_get_context(self->source)) - desc = "attached"; - else - desc = "unattached"; - } else { - desc = "destroyed"; - } - - if (type) - g_snprintf(buf, sizeof(buf), "<%s glib %s source at 0x%lx>", - desc, type, (long) self); - else - g_snprintf(buf, sizeof(buf), "<%s glib source at 0x%lx>", - desc, (long) self); - - return PyString_FromString(buf); -} - -static PyObject * -pyg_source_attach(PyGSource *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "context", NULL }; - PyGMainContext *py_context = NULL; - GMainContext *context = NULL; - guint id; - - if (!PyArg_ParseTupleAndKeywords (args, kwargs, - "|O!:attach", kwlist, - &PyGMainContext_Type, &py_context)) - return NULL; - - if (py_context) - context = py_context->context; - - CHECK_DESTROYED(self, NULL); - - if (self->python_source) { - PyGRealSource *pysource = (PyGRealSource *)self->source; - Py_INCREF(pysource->obj); - } - - id = g_source_attach(self->source, context); - return PyInt_FromLong(id); -} - -static PyObject * -pyg_source_destroy(PyGSource *self) -{ - CHECK_DESTROYED(self, NULL); - - if (self->python_source && self->source->context) { - PyGRealSource *pysource = (PyGRealSource *)self->source; - Py_DECREF(pysource->obj); - } - - g_source_destroy(self->source); - self->source = NULL; - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -pyg_source_set_callback(PyGSource *self, PyObject *args) -{ - PyObject *first, *callback, *cbargs = NULL, *data; - gint len; - - CHECK_DESTROYED(self, NULL); - - len = PyTuple_Size (args); - if (len < 1) { - PyErr_SetString(PyExc_TypeError, - "set_callback requires at least 1 argument"); - return NULL; - } - - first = PySequence_GetSlice(args, 0, 1); - if (!PyArg_ParseTuple(first, "O:set_callback", &callback)) { - Py_DECREF (first); - return NULL; - } - Py_DECREF(first); - - if (!PyCallable_Check(callback)) { - PyErr_SetString(PyExc_TypeError, "first argument not callable"); - return NULL; - } - - cbargs = PySequence_GetSlice(args, 1, len); - if (cbargs == NULL) - return NULL; - - data = Py_BuildValue("(ON)", callback, cbargs); - if (data == NULL) - return NULL; - - g_source_set_callback(self->source, pyg_handler_marshal, data, - pyg_destroy_notify); - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -pyg_source_get_context(PyGSource *self) -{ - GMainContext *context; - - CHECK_DESTROYED(self, NULL); - - context = g_source_get_context(self->source); - - if (context) { - return pyglib_main_context_new(context); - } else { - Py_INCREF(Py_None); - return Py_None; - } -} - -static PyObject * -pyg_source_add_poll(PyGSource *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "fd", NULL }; - PyGPollFD *fd; - - if (!self->python_source) { - PyErr_SetString(PyExc_TypeError, - "add_poll can only be used with sources " - "implemented in python"); - return NULL; - } - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O!:add_poll", kwlist, - &PyGPollFD_Type, &fd)) - return NULL; - - CHECK_DESTROYED(self, NULL); - - g_source_add_poll(self->source, &fd->pollfd); - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -pyg_source_remove_poll(PyGSource *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "fd", NULL }; - PyGPollFD *fd; - - if (!self->python_source) { - PyErr_SetString(PyExc_TypeError, - "remove_poll can only be used with sources " - "implemented in python"); - return NULL; - } - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O!:remove_poll", kwlist, - &PyGPollFD_Type, &fd)) - return NULL; - - CHECK_DESTROYED(self, NULL); - - g_source_remove_poll(self->source, &fd->pollfd); - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -pyg_source_get_current_time(PyGSource *self) -{ - GTimeVal timeval; - double ret; - - CHECK_DESTROYED(self, NULL); - - g_source_get_current_time(self->source, &timeval); - ret = (double)timeval.tv_sec + (double)timeval.tv_usec * 0.000001; - return PyFloat_FromDouble(ret); -} - -static PyMethodDef pyg_source_methods[] = { - { "attach", (PyCFunction)pyg_source_attach, METH_KEYWORDS }, - { "destroy", (PyCFunction)pyg_source_destroy, METH_NOARGS }, - { "set_callback", (PyCFunction)pyg_source_set_callback, METH_VARARGS }, - { "get_context", (PyCFunction)pyg_source_get_context, METH_NOARGS }, - { "add_poll", (PyCFunction)pyg_source_add_poll, METH_KEYWORDS }, - { "remove_poll", (PyCFunction)pyg_source_remove_poll, METH_KEYWORDS }, - { "get_current_time", (PyCFunction)pyg_source_get_current_time, METH_NOARGS }, - { NULL, NULL, 0 } -}; - -static PyObject * -pyg_source_get_dict(PyGSource *self, void *closure) -{ - if (self->inst_dict == NULL) { - self->inst_dict = PyDict_New(); - if (self->inst_dict == NULL) - return NULL; - } - - Py_INCREF(self->inst_dict); - return self->inst_dict; -} - -static PyObject * -pyg_source_get_priority(PyGSource *self, void *closure) -{ - CHECK_DESTROYED(self, NULL); - - return PyInt_FromLong(g_source_get_priority(self->source)); -} - -static int -pyg_source_set_priority(PyGSource *self, PyObject *value, void *closure) -{ - CHECK_DESTROYED(self, -1); - - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, "cannot delete priority"); - return -1; - } - - if (!PyInt_Check(value)) { - PyErr_SetString(PyExc_TypeError, "type mismatch"); - return -1; - } - - g_source_set_priority(self->source, PyInt_AsLong(value)); - - return 0; -} - -static PyObject * -pyg_source_get_can_recurse(PyGSource *self, void *closure) -{ - CHECK_DESTROYED(self, NULL); - - return PyBool_FromLong(g_source_get_can_recurse(self->source)); -} - -static int -pyg_source_set_can_recurse(PyGSource *self, PyObject *value, void *closure) -{ - CHECK_DESTROYED(self, -1); - - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, "cannot delete can_recurse"); - return -1; - } - - g_source_set_can_recurse(self->source, PyObject_IsTrue(value)); - - return 0; -} - -static PyObject * -pyg_source_get_id(PyGSource *self, void *closure) -{ - CHECK_DESTROYED(self, NULL); - - if (g_source_get_context(self->source) == NULL) { - PyErr_SetString(PyExc_RuntimeError, "source is not attached"); - return NULL; - } - - return PyInt_FromLong(g_source_get_id(self->source)); -} - -static PyGetSetDef pyg_source_getsets[] = { - { "__dict__", (getter)pyg_source_get_dict, (setter)0 }, - {"priority", (getter)pyg_source_get_priority, (setter)pyg_source_set_priority }, - {"can_recurse", (getter)pyg_source_get_can_recurse, (setter)pyg_source_set_can_recurse }, - {"id", (getter)pyg_source_get_id, (setter)0 }, - {NULL, 0, 0} -}; - -static PyObject * -pyg_source_repr(PyGSource *self) -{ - return source_repr(self, NULL); -} - -static int -pyg_source_traverse(PyGSource *self, visitproc visit, void *arg) -{ - int ret = 0; - - if (self->inst_dict) ret = visit(self->inst_dict, arg); - if (ret != 0) return ret; - - return 0; -} - -static int -pyg_source_clear(PyGSource *self) -{ - PyObject *tmp; - - tmp = self->inst_dict; - self->inst_dict = NULL; - Py_XDECREF(tmp); - - if (self->source) { - g_source_unref(self->source); - self->source = NULL; - } - - return 0; -} - -static void -pyg_source_dealloc(PyGSource *self) -{ - PyObject_ClearWeakRefs((PyObject *)self); - - PyObject_GC_UnTrack((PyObject *)self); - - pyg_source_clear(self); - - PyObject_GC_Del(self); -} - -static gboolean -pyg_source_prepare(GSource *source, gint *timeout) -{ - PyGRealSource *pysource = (PyGRealSource *)source; - PyObject *t; - gboolean ret = FALSE; - gboolean got_err = TRUE; - PyGILState_STATE state; - - state = pyglib_gil_state_ensure(); - - t = PyObject_CallMethod(pysource->obj, "prepare", NULL); - - if (t == NULL) { - goto bail; - } else if (!PyObject_IsTrue(t)) { - got_err = FALSE; - goto bail; - } else if (!PyTuple_Check(t)) { - PyErr_SetString(PyExc_TypeError, - "source prepare function must return a tuple or False"); - goto bail; - } else if (PyTuple_Size(t) != 2) { - PyErr_SetString(PyExc_TypeError, - "source prepare function return tuple must be exactly " - "2 elements long"); - goto bail; - } - - ret = PyObject_IsTrue(PyTuple_GET_ITEM(t, 0)); - *timeout = PyInt_AsLong(PyTuple_GET_ITEM(t, 1)); - - if (*timeout == -1 && PyErr_Occurred()) { - ret = FALSE; - goto bail; - } - - got_err = FALSE; - -bail: - if (got_err) - PyErr_Print(); - - Py_XDECREF(t); - - pyglib_gil_state_release(state); - - return ret; -} - -static gboolean -pyg_source_check(GSource *source) -{ - PyGRealSource *pysource = (PyGRealSource *)source; - PyObject *t; - gboolean ret; - PyGILState_STATE state; - - state = pyglib_gil_state_ensure(); - - t = PyObject_CallMethod(pysource->obj, "check", NULL); - - if (t == NULL) { - PyErr_Print(); - ret = FALSE; - } else { - ret = PyObject_IsTrue(t); - Py_DECREF(t); - } - - pyglib_gil_state_release(state); - - return ret; -} - -static gboolean -pyg_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) -{ - PyGRealSource *pysource = (PyGRealSource *)source; - PyObject *func, *args, *tuple, *t; - gboolean ret; - PyGILState_STATE state; - - state = pyglib_gil_state_ensure(); - - if (callback) { - tuple = user_data; - - func = PyTuple_GetItem(tuple, 0); - args = PyTuple_GetItem(tuple, 1); - } else { - func = Py_None; - args = Py_None; - } - - t = PyObject_CallMethod(pysource->obj, "dispatch", "OO", func, args); - - if (t == NULL) { - PyErr_Print(); - ret = FALSE; - } else { - ret = PyObject_IsTrue(t); - Py_DECREF(t); - } - - pyglib_gil_state_release(state); - - return ret; -} - -static void -pyg_source_finalize(GSource *source) -{ - PyGRealSource *pysource = (PyGRealSource *)source; - PyObject *func, *t; - PyGILState_STATE state; - - state = pyglib_gil_state_ensure(); - - func = PyObject_GetAttrString(pysource->obj, "finalize"); - if (func) { - t = PyObject_CallObject(func, NULL); - Py_DECREF(func); - - if (t == NULL) { - PyErr_Print(); - } else { - Py_DECREF(t); - } - } - - pyglib_gil_state_release(state); -} - -static GSourceFuncs pyg_source_funcs = -{ - pyg_source_prepare, - pyg_source_check, - pyg_source_dispatch, - pyg_source_finalize -}; - -static int -pyg_source_init(PyGSource *self, PyObject *args, PyObject *kwargs) -{ - PyGRealSource *pysource; - - self->source = g_source_new(&pyg_source_funcs, sizeof(PyGRealSource)); - - pysource = (PyGRealSource *)self->source; - pysource->obj = (PyObject*)self; - - self->inst_dict = NULL; - self->weakreflist = NULL; - - self->python_source = TRUE; - - return 0; -} - -static void -pyg_source_free(PyObject *op) -{ - PyObject_GC_Del(op); -} - -PyTypeObject PyGSource_Type = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - "gobject.Source", /* tp_name */ - sizeof(PyGSource), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pyg_source_dealloc, /* tp_dealloc */ - (printfunc)0, /* tp_print */ - (getattrfunc)0, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ - (cmpfunc)0, /* tp_compare */ - (reprfunc)pyg_source_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)0, /* tp_str */ - (getattrofunc)0, /* tp_getattro */ - (setattrofunc)0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /* tp_flags */ - NULL, /* tp_doc */ - (traverseproc)pyg_source_traverse, /* tp_traverse */ - (inquiry)pyg_source_clear, /* tp_clear */ - (richcmpfunc)0, /* tp_richcompare */ - offsetof(PyGSource, weakreflist), /* tp_weaklistoffset */ - (getiterfunc)0, /* tp_iter */ - (iternextfunc)0, /* tp_iternext */ - pyg_source_methods, /* tp_methods */ - 0, /* tp_members */ - pyg_source_getsets, /* tp_getset */ - (PyTypeObject *)0, /* tp_base */ - (PyObject *)0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(PyGSource, inst_dict), /* tp_dictoffset */ - (initproc)pyg_source_init, /* tp_init */ - (allocfunc)0, /* tp_alloc */ - (newfunc)0, /* tp_new */ - (freefunc)pyg_source_free, /* tp_free */ - (inquiry)0, /* tp_is_gc */ - (PyObject *)0, /* tp_bases */ -}; - -static PyObject * -pyg_idle_repr(PyGSource *self) -{ - return source_repr(self, "idle"); -} - -static int -pyg_idle_init(PyGSource *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "priority", NULL }; - gint priority = G_PRIORITY_DEFAULT_IDLE; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|i:gobject.Idle.__init__", kwlist, - &priority)) - return -1; - - self->source = g_idle_source_new (); - - if (priority != G_PRIORITY_DEFAULT_IDLE) - g_source_set_priority(self->source, priority); - - self->inst_dict = NULL; - self->weakreflist = NULL; - - self->python_source = FALSE; - - return 0; -} - -PyTypeObject PyGIdle_Type = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - "gobject.Idle", /* tp_name */ - sizeof(PyGSource), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)0, /* tp_dealloc */ - (printfunc)0, /* tp_print */ - (getattrfunc)0, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ - (cmpfunc)0, /* tp_compare */ - (reprfunc)pyg_idle_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)0, /* tp_str */ - (getattrofunc)0, /* tp_getattro */ - (setattrofunc)0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - NULL, /* tp_doc */ - (traverseproc)0, /* tp_traverse */ - (inquiry)0, /* tp_clear */ - (richcmpfunc)0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)0, /* tp_iter */ - (iternextfunc)0, /* tp_iternext */ - NULL, /* tp_methods */ - NULL, /* tp_members */ - NULL, /* tp_getset */ - (PyTypeObject *)&PyGSource_Type, /* tp_base */ - (PyObject *)0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pyg_idle_init, /* tp_init */ - (allocfunc)0, /* tp_alloc */ - (newfunc)0, /* tp_new */ - (freefunc)0, /* tp_free */ - (inquiry)0, /* tp_is_gc */ - (PyObject *)0, /* tp_bases */ -}; - -static PyObject * -pyg_timeout_repr(PyGSource *self) -{ - return source_repr(self, "timeout"); -} - -static int -pyg_timeout_init(PyGSource *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "interval", "priority", NULL }; - gint priority = G_PRIORITY_DEFAULT; - guint interval; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "I|i:gobject.Timeout.__init__", kwlist, - &interval, &priority)) - return -1; - - self->source = g_timeout_source_new(interval); - - if (priority != G_PRIORITY_DEFAULT) - g_source_set_priority(self->source, priority); - - self->inst_dict = NULL; - self->weakreflist = NULL; - - self->python_source = FALSE; - - return 0; -} - -PyTypeObject PyGTimeout_Type = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - "gobject.Timeout", /* tp_name */ - sizeof(PyGSource), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)0, /* tp_dealloc */ - (printfunc)0, /* tp_print */ - (getattrfunc)0, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ - (cmpfunc)0, /* tp_compare */ - (reprfunc)pyg_timeout_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)0, /* tp_str */ - (getattrofunc)0, /* tp_getattro */ - (setattrofunc)0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - NULL, /* tp_doc */ - (traverseproc)0, /* tp_traverse */ - (inquiry)0, /* tp_clear */ - (richcmpfunc)0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)0, /* tp_iter */ - (iternextfunc)0, /* tp_iternext */ - NULL, /* tp_methods */ - NULL, /* tp_members */ - NULL, /* tp_getset */ - (PyTypeObject *)&PyGSource_Type, /* tp_base */ - (PyObject *)0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pyg_timeout_init, /* tp_init */ - (allocfunc)0, /* tp_alloc */ - (newfunc)0, /* tp_new */ - (freefunc)0, /* tp_free */ - (inquiry)0, /* tp_is_gc */ - (PyObject *)0, /* tp_bases */ -}; - -static PyMemberDef pyg_poll_fd_members[] = { - { "fd", T_INT, offsetof(PyGPollFD, pollfd.fd), RO }, - { "events", T_USHORT, offsetof(PyGPollFD, pollfd.events), RO }, - { "revents", T_USHORT, offsetof(PyGPollFD, pollfd.revents), RO }, - { NULL, 0, 0, 0 } -}; - -static void -pyg_poll_fd_dealloc(PyGPollFD *self) -{ - Py_XDECREF(self->fd_obj); - PyObject_DEL(self); -} - -static PyObject * -pyg_poll_fd_repr(PyGPollFD *self) -{ - return PyString_FromFormat("", - self->pollfd.fd, self->pollfd.events, - (long)self); -} - -static int -pyg_poll_fd_init(PyGPollFD *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "fd", "events", NULL }; - PyObject *o; - gint fd; - gushort events; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "OH:gobject.PollFD.__init__", kwlist, - &o, &events)) - return -1; - - fd = PyObject_AsFileDescriptor(o); - if (fd == -1) - return -1; - - self->pollfd.fd = fd; - self->pollfd.events = events; - self->pollfd.revents = 0; - - Py_INCREF(o); - self->fd_obj = o; - - return 0; -} - -PyTypeObject PyGPollFD_Type = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - "gobject.PollFD", /* tp_name */ - sizeof(PyGPollFD), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pyg_poll_fd_dealloc, /* tp_dealloc */ - (printfunc)0, /* tp_print */ - (getattrfunc)0, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ - (cmpfunc)0, /* tp_compare */ - (reprfunc)pyg_poll_fd_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)0, /* tp_str */ - (getattrofunc)0, /* tp_getattro */ - (setattrofunc)0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - NULL, /* tp_doc */ - (traverseproc)0, /* tp_traverse */ - (inquiry)0, /* tp_clear */ - (richcmpfunc)0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)0, /* tp_iter */ - (iternextfunc)0, /* tp_iternext */ - 0, /* tp_methods */ - pyg_poll_fd_members, /* tp_members */ - 0, /* tp_getset */ - (PyTypeObject *)0, /* tp_base */ - (PyObject *)0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pyg_poll_fd_init, /* tp_init */ - (allocfunc)0, /* tp_alloc */ - (newfunc)0, /* tp_new */ - (freefunc)0, /* tp_free */ - (inquiry)0, /* tp_is_gc */ - (PyObject *)0, /* tp_bases */ -}; -- cgit