summaryrefslogtreecommitdiffstats
path: root/glib
diff options
context:
space:
mode:
authorJohan Dahlin <johan@gnome.org>2008-07-21 17:27:22 +0000
committerJohan Dahlin <johan@src.gnome.org>2008-07-21 17:27:22 +0000
commitbf49647a03923975eb24ce634dae8254553db8de (patch)
treefac72b5b605789d7fa566332bd6a986b148a1ca5 /glib
parent39cf2d9ca4fc9b50984ec172282d33b1843fceee (diff)
Move over Source, IOChannel, Idle, Timeout and PollFD to glib from
2008-07-21 Johan Dahlin <johan@gnome.org> * 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
Diffstat (limited to 'glib')
-rw-r--r--glib/Makefile.am12
-rw-r--r--glib/glibmodule.c79
-rw-r--r--glib/pygiochannel.c818
-rw-r--r--glib/pygiochannel.h29
-rw-r--r--glib/pyglib-private.h6
-rw-r--r--glib/pyglib.c96
-rw-r--r--glib/pyglib.h6
-rw-r--r--glib/pygsource.c860
-rw-r--r--glib/pygsource.h39
-rw-r--r--glib/pygspawn.c2
-rw-r--r--glib/pygspawn.h2
11 files changed, 1881 insertions, 68 deletions
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 <config.h>
+#endif
+
+#include <Python.h>
+#include <pythread.h>
+#include <structmember.h> /* 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 <manish.singh@oracle.com>
+ *
+ * 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 <config.h>
+#endif
+
+#include <Python.h>
+#include <pythread.h>
+#include <structmember.h> /* 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("<GPollFD %d (%d) at 0x%lx>",
+ 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);