dbus/proxies.py: Give Interface some properties. Vastly simplify __getattr__ on Inter...
[dbus-python-phuang.git] / _dbus_bindings / bus.c
blob2ae0383e75ae7221fec2f853938ef3284808757c
1 /* Implementation of Bus, a subtype of Connection.
3 * Copyright (C) 2006 Collabora Ltd.
5 * Licensed under the Academic Free License version 2.1
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "dbus_bindings-internal.h"
24 #include "conn-internal.h"
26 PyDoc_STRVAR(Bus_tp_doc,
27 "If the address is an int it must be one of the constants BUS_SESSION,\n"
28 "BUS_SYSTEM, BUS_STARTER; if a string, it must be a D-Bus address.\n"
29 "The default is BUS_SESSION.\n"
30 "\n"
31 "Constructor::\n"
32 "\n"
33 " BusImplementation([address: str or int])\n"
36 /* Bus definition =================================================== */
38 static PyTypeObject BusType;
40 #define Bus_Check(ob) PyObject_TypeCheck(ob, &BusType)
42 /* Bus methods ====================================================== */
44 static PyObject *
45 Bus_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
47 PyObject *first = NULL, *mainloop = NULL;
48 DBusConnection *conn;
49 DBusError error;
50 Connection *self;
51 dbus_bool_t ret;
52 long type;
53 static char *argnames[] = {"address_or_type", "mainloop", NULL};
55 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", argnames,
56 &first, &mainloop)) {
57 return NULL;
60 dbus_error_init(&error);
62 if (first && PyString_Check(first)) {
63 /* It's a custom address. First connect to it, then register. */
65 self = (Connection *)(DBusPyConnection_Type.tp_new)(cls, args, kwargs);
66 if (!self) return NULL;
67 TRACE(self);
69 Py_BEGIN_ALLOW_THREADS
70 ret = dbus_bus_register(self->conn, &error);
71 Py_END_ALLOW_THREADS
72 if (!ret) {
73 DBusPyException_ConsumeError(&error);
74 Py_DECREF(self);
75 return NULL;
78 return (PyObject *)self;
81 /* If the first argument isn't a string, it must be an integer
82 representing one of the well-known bus types. */
84 if (first && !PyInt_Check(first)) {
85 PyErr_SetString(PyExc_TypeError, "A string address or an integer "
86 "bus type is required");
87 return NULL;
89 if (first) {
90 type = PyInt_AsLong(first);
92 else {
93 type = DBUS_BUS_SESSION;
96 if (type != DBUS_BUS_SESSION && type != DBUS_BUS_SYSTEM
97 && type != DBUS_BUS_STARTER) {
98 PyErr_Format(PyExc_ValueError, "Unknown bus type %d", (int)type);
99 return NULL;
102 Py_BEGIN_ALLOW_THREADS
103 conn = dbus_bus_get_private(type, &error);
104 Py_END_ALLOW_THREADS
106 if (!conn) {
107 DBusPyException_ConsumeError(&error);
108 return NULL;
110 return DBusPyConnection_NewConsumingDBusConnection(cls, conn, mainloop);
113 PyDoc_STRVAR(Bus_get_unique_name__doc__,
114 "get_unique_name() -> str\n\n"
115 "Return this application's unique name on this bus.\n");
116 static PyObject *
117 Bus_get_unique_name(Connection *self, PyObject *args UNUSED)
119 const char *name;
121 TRACE(self);
122 DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
123 Py_BEGIN_ALLOW_THREADS
124 name = dbus_bus_get_unique_name(self->conn);
125 Py_END_ALLOW_THREADS
126 if (!name) {
127 /* shouldn't happen, but C subtypes could have done something stupid */
128 PyErr_SetString(DBusPyException, "Unable to retrieve unique name");
129 return NULL;
131 return PyString_FromString(name);
134 PyDoc_STRVAR(Bus_get_unix_user__doc__,
135 "get_unix_user(bus_name) -> int\n"
136 "\n"
137 "Get the numeric uid of the process which owns the given bus name\n"
138 "on the connected bus daemon.\n"
139 "\n"
140 ":Parameters:\n"
141 " `bus_name` : str\n"
142 " A bus name (may be either a unique name or a well-known name)\n"
144 static PyObject *
145 Bus_get_unix_user(Connection *self, PyObject *args)
147 DBusError error;
148 unsigned long uid;
149 const char *bus_name;
151 TRACE(self);
152 DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
153 if (!PyArg_ParseTuple(args, "s:get_unix_user", &bus_name)) {
154 return NULL;
157 dbus_error_init(&error);
158 Py_BEGIN_ALLOW_THREADS
159 uid = dbus_bus_get_unix_user(self->conn, bus_name, &error);
160 Py_END_ALLOW_THREADS
161 if (uid == (unsigned long)(-1)) return DBusPyException_ConsumeError(&error);
162 return PyLong_FromUnsignedLong(uid);
165 PyDoc_STRVAR(Bus_start_service_by_name__doc__,
166 "start_service_by_name(bus_name)\n\
168 Start a service which will implement the given bus name on this\n\
169 Bus.\n\
171 :Parameters:\n\
172 `bus_name` : str\n\
173 The well-known bus name for which an implementation is required\n\
175 :Returns: A tuple of 2 elements. The first is always True, the second is\n\
176 either START_REPLY_SUCCESS or START_REPLY_ALREADY_RUNNING.\n\
178 :Raises DBusException: if the service could not be started.\n\
180 FIXME: Fix return signature?\n\
182 static PyObject *
183 Bus_start_service_by_name(Connection *self, PyObject *args)
185 DBusError error;
186 const char *bus_name;
187 dbus_uint32_t ret;
188 dbus_bool_t success;
190 TRACE(self);
191 DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
192 if (!PyArg_ParseTuple(args, "s:start_service_by_name", &bus_name)) {
193 return NULL;
195 dbus_error_init(&error);
196 Py_BEGIN_ALLOW_THREADS
197 success = dbus_bus_start_service_by_name(self->conn, bus_name,
198 0 /* flags */, &ret, &error);
199 Py_END_ALLOW_THREADS
200 if (!success) {
201 return DBusPyException_ConsumeError(&error);
203 return Py_BuildValue("(Ol)", Py_True, (long)ret);
206 /* FIXME: signal IN_QUEUE, EXISTS by exception? */
207 PyDoc_STRVAR(Bus_request_name__doc__, "");
208 static PyObject *
209 Bus_request_name(Connection *self, PyObject *args)
211 unsigned int flags = 0;
212 const char *bus_name;
213 int ret;
214 DBusError error;
216 TRACE(self);
217 DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
218 if (!PyArg_ParseTuple(args, "s|I:request_name", &bus_name, &flags)) {
219 return NULL;
221 if (!dbus_py_validate_bus_name(bus_name, 0, 1)) return NULL;
223 dbus_error_init(&error);
224 Py_BEGIN_ALLOW_THREADS
225 ret = dbus_bus_request_name(self->conn, bus_name, flags, &error);
226 Py_END_ALLOW_THREADS
227 if (ret == -1) return DBusPyException_ConsumeError(&error);
229 return PyInt_FromLong(ret);
232 PyDoc_STRVAR(Bus_release_name__doc__, "");
233 static PyObject *
234 Bus_release_name(Connection *self, PyObject *args)
236 const char *bus_name;
237 int ret;
238 DBusError error;
240 TRACE(self);
241 DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
242 if (!PyArg_ParseTuple(args, "s:release_name", &bus_name)) return NULL;
244 dbus_error_init(&error);
245 Py_BEGIN_ALLOW_THREADS
246 ret = dbus_bus_release_name(self->conn, bus_name, &error);
247 Py_END_ALLOW_THREADS
248 if (ret == -1) return DBusPyException_ConsumeError(&error);
250 return PyInt_FromLong(ret);
253 PyDoc_STRVAR(Bus_name_has_owner__doc__,
254 "name_has_owner(bus_name) -> bool\n\n"
255 "Return True if and only if the given bus name has an owner on this bus.\n");
256 static PyObject *
257 Bus_name_has_owner(Connection *self, PyObject *args)
259 const char *bus_name;
260 int ret;
261 DBusError error;
263 TRACE(self);
264 DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
265 if (!PyArg_ParseTuple(args, "s:name_has_owner", &bus_name)) return NULL;
266 dbus_error_init(&error);
267 Py_BEGIN_ALLOW_THREADS
268 ret = dbus_bus_name_has_owner(self->conn, bus_name, &error);
269 Py_END_ALLOW_THREADS
270 if (dbus_error_is_set(&error)) {
271 return DBusPyException_ConsumeError(&error);
273 return PyBool_FromLong(ret);
276 PyDoc_STRVAR(Bus_add_match_string__doc__,
277 "add_match_string(rule)\n\n"
278 "Arrange for this application to receive messages on the bus that match\n"
279 "the given rule. This version will block and raises DBusException on error.\n");
280 static PyObject *
281 Bus_add_match_string(Connection *self, PyObject *args)
283 const char *rule;
284 DBusError error;
286 TRACE(self);
287 DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
288 if (!PyArg_ParseTuple(args, "s:add_match", &rule)) return NULL;
289 dbus_error_init(&error);
290 Py_BEGIN_ALLOW_THREADS
291 dbus_bus_add_match(self->conn, rule, &error);
292 Py_END_ALLOW_THREADS
293 if (dbus_error_is_set(&error)) {
294 return DBusPyException_ConsumeError(&error);
296 Py_RETURN_NONE;
299 PyDoc_STRVAR(Bus_add_match_string_non_blocking__doc__,
300 "add_match_string_non_blocking(rule)\n\n"
301 "Arrange for this application to receive messages on the bus that match\n"
302 "the given rule. This version does not block, but any errors will be\n"
303 "ignored.\n");
304 static PyObject *
305 Bus_add_match_string_non_blocking(Connection *self, PyObject *args)
307 const char *rule;
309 DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
310 if (!PyArg_ParseTuple(args, "s:add_match", &rule)) return NULL;
311 Py_BEGIN_ALLOW_THREADS
312 dbus_bus_add_match(self->conn, rule, NULL);
313 Py_END_ALLOW_THREADS
314 Py_RETURN_NONE;
317 PyDoc_STRVAR(Bus_remove_match_string__doc__,
318 "remove_match_string(rule)\n\n"
319 "Remove the given match rule; if it has been added more than once,\n"
320 "remove one of the identical copies, leaving the others active.\n"
321 "This version blocks, and raises DBusException on error.\n");
322 static PyObject *
323 Bus_remove_match_string(Connection *self, PyObject *args)
325 const char *rule;
326 DBusError error;
328 TRACE(self);
329 DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
330 if (!PyArg_ParseTuple(args, "s:remove_match", &rule)) return NULL;
331 dbus_error_init(&error);
332 Py_BEGIN_ALLOW_THREADS
333 dbus_bus_remove_match(self->conn, rule, &error);
334 Py_END_ALLOW_THREADS
335 if (dbus_error_is_set(&error)) {
336 return DBusPyException_ConsumeError(&error);
338 Py_RETURN_NONE;
341 PyDoc_STRVAR(Bus_remove_match_string_non_blocking__doc__,
342 "remove_match_string_non_blocking(rule)\n\n"
343 "Remove the given match rule; if it has been added more than once,\n"
344 "remove one of the identical copies, leaving the others active.\n"
345 "This version does not block, but causes any errors to be ignored.\n");
346 static PyObject *
347 Bus_remove_match_string_non_blocking(Connection *self, PyObject *args)
349 const char *rule;
351 TRACE(self);
352 DBUS_PY_RAISE_VIA_NULL_IF_FAIL(self->conn);
353 if (!PyArg_ParseTuple(args, "s:remove_match", &rule)) return NULL;
354 Py_BEGIN_ALLOW_THREADS
355 dbus_bus_remove_match(self->conn, rule, NULL);
356 Py_END_ALLOW_THREADS
357 Py_RETURN_NONE;
360 /* Bus type object ================================================== */
362 static struct PyMethodDef Bus_tp_methods[] = {
363 #define ENTRY(name, flags) {#name, (PyCFunction)Bus_##name, flags, Bus_##name##__doc__},
364 ENTRY(get_unique_name, METH_NOARGS)
365 ENTRY(get_unix_user, METH_VARARGS)
366 ENTRY(start_service_by_name, METH_VARARGS)
367 ENTRY(request_name, METH_VARARGS)
368 ENTRY(release_name, METH_VARARGS)
369 ENTRY(name_has_owner, METH_VARARGS)
370 ENTRY(add_match_string, METH_VARARGS)
371 ENTRY(add_match_string_non_blocking, METH_VARARGS)
372 ENTRY(remove_match_string, METH_VARARGS)
373 ENTRY(remove_match_string_non_blocking, METH_VARARGS)
374 #undef ENTRY
375 {NULL},
378 static PyTypeObject BusType = {
379 PyObject_HEAD_INIT(NULL)
380 0, /*ob_size*/
381 "_dbus_bindings.BusImplementation", /*tp_name*/
382 0, /*tp_basicsize*/
383 0, /*tp_itemsize*/
384 /* methods */
385 0, /*tp_dealloc*/
386 0, /*tp_print*/
387 0, /*tp_getattr*/
388 0, /*tp_setattr*/
389 0, /*tp_compare*/
390 0, /*tp_repr*/
391 0, /*tp_as_number*/
392 0, /*tp_as_sequence*/
393 0, /*tp_as_mapping*/
394 0, /*tp_hash*/
395 0, /*tp_call*/
396 0, /*tp_str*/
397 0, /*tp_getattro*/
398 0, /*tp_setattro*/
399 0, /*tp_as_buffer*/
400 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
401 Bus_tp_doc, /*tp_doc*/
402 0, /*tp_traverse*/
403 0, /*tp_clear*/
404 0, /*tp_richcompare*/
405 0, /*tp_weaklistoffset*/
406 0, /*tp_iter*/
407 0, /*tp_iternext*/
408 Bus_tp_methods, /*tp_methods*/
409 0, /*tp_members*/
410 0, /*tp_getset*/
411 DEFERRED_ADDRESS(&ConnectionType), /*tp_base*/
412 0, /*tp_dict*/
413 0, /*tp_descr_get*/
414 0, /*tp_descr_set*/
415 0, /*tp_dictoffset*/
416 0, /*tp_init*/
417 0, /*tp_alloc*/
418 Bus_tp_new, /*tp_new*/
419 0, /*tp_free*/
420 0, /*tp_is_gc*/
423 dbus_bool_t
424 dbus_py_init_bus_types(void)
426 BusType.tp_base = &DBusPyConnection_Type;
427 if (PyType_Ready(&BusType) < 0) return 0;
428 return 1;
431 dbus_bool_t
432 dbus_py_insert_bus_types(PyObject *this_module)
434 if (PyModule_AddObject(this_module, "BusImplementation",
435 (PyObject *)&BusType) < 0) return 0;
436 return 1;
439 /* vim:set ft=c cino< sw=4 sts=4 et: */