/* Implementation of main-loop integration for dbus-python.
*
* Copyright (C) 2006 Collabora Ltd.
* Copyright (C) 2008 Huang Peng
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include "dbus_bindings-internal.h"
/* Native mainloop wrapper ========================================= */
PyDoc_STRVAR(NativeMainLoop_tp_doc,
"Object representing D-Bus main loop integration done in native code.\n"
"Cannot be instantiated directly.\n"
);
static PyTypeObject NativeMainLoop_Type;
DEFINE_CHECK(NativeMainLoop)
typedef struct {
PyObject_HEAD
/* Called with the GIL held, should set a Python exception on error */
dbus_bool_t (*set_up_connection_cb)(DBusConnection *, void *);
dbus_bool_t (*set_up_server_cb)(DBusServer *, void *);
/* Called in a destructor. Must not touch the exception state (use
* PyErr_Fetch and PyErr_Restore if necessary). */
void (*free_cb)(void *);
void *data;
} NativeMainLoop;
static void NativeMainLoop_tp_dealloc(NativeMainLoop *self)
{
if (self->data && self->free_cb) {
(self->free_cb)(self->data);
}
PyObject_Del((PyObject *)self);
}
static PyTypeObject NativeMainLoop_Type = {
PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
"dbus.mainloop.NativeMainLoop",
sizeof(NativeMainLoop),
0,
(destructor)NativeMainLoop_tp_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
NativeMainLoop_tp_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
/* deliberately not callable! */
0, /* tp_new */
};
/* Internal C API for Connection, Bus, Server ======================= */
dbus_bool_t
dbus_py_check_mainloop_sanity(PyObject *mainloop)
{
if (NativeMainLoop_Check(mainloop)) {
return TRUE;
}
PyErr_SetString(PyExc_TypeError,
"A dbus.mainloop.NativeMainLoop instance is required");
return FALSE;
}
dbus_bool_t
dbus_py_set_up_connection(PyObject *conn, PyObject *mainloop)
{
if (NativeMainLoop_Check(mainloop)) {
/* Native mainloops are allowed to do arbitrary strange things */
NativeMainLoop *nml = (NativeMainLoop *)mainloop;
DBusConnection *dbc = DBusPyConnection_BorrowDBusConnection(conn);
if (!dbc) {
return FALSE;
}
return (nml->set_up_connection_cb)(dbc, nml->data);
}
PyErr_SetString(PyExc_TypeError,
"A dbus.mainloop.NativeMainLoop instance is required");
return FALSE;
}
dbus_bool_t
dbus_py_set_up_server(PyObject *server, PyObject *mainloop)
{
if (NativeMainLoop_Check(mainloop)) {
/* Native mainloops are allowed to do arbitrary strange things */
NativeMainLoop *nml = (NativeMainLoop *)mainloop;
DBusServer *dbs = DBusPyServer_BorrowDBusServer(server);
if (!dbs) {
return FALSE;
}
return (nml->set_up_server_cb)(dbs, nml->data);
}
PyErr_SetString(PyExc_TypeError,
"A dbus.mainloop.NativeMainLoop instance is required");
return FALSE;
}
/* C API ============================================================ */
PyObject *
DBusPyNativeMainLoop_New4(dbus_bool_t (*conn_cb)(DBusConnection *, void *),
dbus_bool_t (*server_cb)(DBusServer *, void *),
void (*free_cb)(void *),
void *data)
{
NativeMainLoop *self = PyObject_New(NativeMainLoop, &NativeMainLoop_Type);
if (self) {
self->data = data;
self->free_cb = free_cb;
self->set_up_connection_cb = conn_cb;
self->set_up_server_cb = server_cb;
}
return (PyObject *)self;
}
/* Null mainloop implementation ===================================== */
static dbus_bool_t
noop_main_loop_cb(void *conn_or_server UNUSED, void *data UNUSED)
{
return TRUE;
}
#define noop_conn_cb ((dbus_bool_t (*)(DBusConnection *, void *))(noop_main_loop_cb))
#define noop_server_cb ((dbus_bool_t (*)(DBusServer *, void *))(noop_main_loop_cb))
/* Initialization =================================================== */
dbus_bool_t
dbus_py_init_mainloop(void)
{
if (PyType_Ready (&NativeMainLoop_Type) < 0) return 0;
return 1;
}
dbus_bool_t
dbus_py_insert_mainloop_types(PyObject *this_module)
{
PyObject *null_main_loop = DBusPyNativeMainLoop_New4(noop_conn_cb,
noop_server_cb,
NULL,
NULL);
if (!null_main_loop) return 0;
/* PyModule_AddObject steals a ref */
Py_INCREF (&NativeMainLoop_Type);
if (PyModule_AddObject (this_module, "NativeMainLoop",
(PyObject *)&NativeMainLoop_Type) < 0) return 0;
if (PyModule_AddObject (this_module, "NULL_MAIN_LOOP",
null_main_loop) < 0) return 0;
return 1;
}
/* vim:set ft=c cino< sw=4 sts=4 et: */