Actually commit the numerous copyright-statement changes.
[dbus-python-phuang.git] / _dbus_bindings / bus.c
blob2ae0383e75ae7221fec2f853938ef3284808757c
1 /* Implementation of Bus, a subtype of Connection.
2  *
3  * Copyright (C) 2006 Collabora Ltd.
4  *
5  * Licensed under the Academic Free License version 2.1
6  *
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.
11  *
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.
16  *
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
20  *
21  */
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;
58     }
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;
76         }
78         return (PyObject *)self;
79     }
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;
88     }
89     if (first) {
90         type = PyInt_AsLong(first);
91     }
92     else {
93         type = DBUS_BUS_SESSION;
94     }
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;
100     }
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;
109     }
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;
130     }
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;
155     }
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;
194     }
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);
202     }
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;
220     }
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);
272     }
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);
295     }
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);
337     }
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: */