Quit when requested from the menu
[ladish.git] / dbus / object_path.c
blob9e38d3727e35f846a4e5cc0372f4b2598343d64f
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009 Nedko Arnaudov <nedko@arnaudov.name>
6 * Copyright (C) 2008 Juuso Alasuutari <juuso.alasuutari@gmail.com>
8 **************************************************************************
9 * This file contains D-Bus object path helpers
10 **************************************************************************
12 * LADI Session Handler is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * LADI Session Handler is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
24 * or write to the Free Software Foundation, Inc.,
25 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdarg.h>
32 #include "object_path.h"
33 #include "../common/safety.h"
34 #include "../common/debug.h"
35 #include "introspection.h" /* g_dbus_interface_dtor_introspectable */
36 #include "error.h" /* lash_dbus_error() */
38 static DBusHandlerResult
39 object_path_handler(DBusConnection *connection,
40 DBusMessage *message,
41 void *data);
43 static void
44 object_path_handler_unregister(DBusConnection *conn,
45 void *data);
47 object_path_t *
48 object_path_new(const char *name,
49 void *context,
50 int num_ifaces,
51 ...)
53 if (!name || !name[0] || num_ifaces < 0)
55 lash_error("Invalid arguments");
56 return NULL;
59 lash_debug("Creating object path");
61 object_path_t *path;
62 va_list argp;
63 const interface_t **iface_pptr;
65 path = lash_malloc(1, sizeof(object_path_t));
66 path->name = lash_strdup(name);
67 path->interfaces = lash_malloc(num_ifaces + 2, sizeof(interface_t *));
69 va_start(argp, num_ifaces);
71 iface_pptr = path->interfaces;
72 *iface_pptr = &g_dbus_interface_dtor_introspectable;
73 for (++iface_pptr;
74 (*iface_pptr = va_arg(argp, const interface_t *));
75 ++iface_pptr);
77 va_end(argp);
79 if ((path->introspection = introspection_new(path))) {
80 path->context = context;
81 return path;
84 lash_error("Failed to create object path");
85 object_path_destroy(NULL, path);
87 return NULL;
90 bool
91 object_path_register(DBusConnection *conn,
92 object_path_t *path)
94 if (!conn || !path || !path->name || !path->interfaces) {
95 lash_debug("Invalid arguments");
96 return false;
99 lash_debug("Registering object path");
101 DBusObjectPathVTable vtable =
103 object_path_handler_unregister,
104 object_path_handler,
105 NULL, NULL, NULL, NULL
108 dbus_connection_register_object_path(conn, path->name,
109 &vtable, (void *) path);
111 return true;
114 void object_path_destroy(DBusConnection * connection_ptr, object_path_t * path_ptr)
116 lash_debug("Destroying object path");
118 if (path_ptr)
120 if (connection_ptr != NULL && !dbus_connection_unregister_object_path(connection_ptr, path_ptr->name))
122 lash_error("dbus_connection_unregister_object_path() failed.");
125 if (path_ptr->name)
127 free(path_ptr->name);
128 path_ptr->name = NULL;
131 if (path_ptr->interfaces)
133 free(path_ptr->interfaces);
134 path_ptr->interfaces = NULL;
137 introspection_destroy(path_ptr);
138 free(path_ptr);
140 #ifdef LASH_DEBUG
141 else
143 lash_debug("Nothing to destroy");
145 #endif
149 static DBusHandlerResult
150 object_path_handler(DBusConnection *connection,
151 DBusMessage *message,
152 void *data)
154 const char *interface_name;
155 const interface_t **iface_pptr;
156 method_call_t call;
158 /* Check if the message is a method call. If not, ignore it. */
159 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
160 goto handled;
163 /* Get the invoked method's name and make sure it's non-NULL. */
164 if (!(call.method_name = dbus_message_get_member(message))) {
165 lash_dbus_error(&call, LASH_DBUS_ERROR_UNKNOWN_METHOD,
166 "Received method call with empty method name");
167 goto send_return;
170 /* Initialize our data. */
171 call.connection = connection;
172 call.message = message;
173 call.interface = NULL; /* To be set by the default interface handler */
174 call.context = data;
175 call.reply = NULL;
177 /* Check if there's an interface specified for this method call. */
178 if ((interface_name = dbus_message_get_interface(message))) {
179 for (iface_pptr = (const interface_t **) ((object_path_t *) data)->interfaces;
180 iface_pptr && *iface_pptr;
181 ++iface_pptr) {
182 if (strcmp(interface_name, (*iface_pptr)->name) == 0) {
183 if ((*iface_pptr)->handler(*iface_pptr, &call)) {
184 goto send_return;
187 break;
191 else
193 /* No interface was specified so we have to try them all. This is
194 * dictated by the D-Bus specification which states that method calls
195 * omitting the interface must never be rejected.
198 for (iface_pptr = (const interface_t **) ((object_path_t *) data)->interfaces;
199 iface_pptr && *iface_pptr;
200 ++iface_pptr) {
201 if ((*iface_pptr)->handler(*iface_pptr, &call)) {
202 goto send_return;
207 lash_dbus_error(&call, LASH_DBUS_ERROR_UNKNOWN_METHOD,
208 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist",
209 call.method_name, dbus_message_get_signature(message), interface_name);
211 send_return:
212 method_return_send(&call);
214 handled:
215 return DBUS_HANDLER_RESULT_HANDLED;
218 static void
219 object_path_handler_unregister(DBusConnection *conn,
220 void *data)
222 #ifdef LASH_DEBUG
223 object_path_t *path = data;
224 lash_debug("Message handler of object path %s was unregistered",
225 (path && path->name) ? path->name : "<unknown>");
226 #endif /* LASH_DEBUG */
229 /* EOF */