2 * Copyright (C) 2007-2008 Kim Woelders
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies of the Software, its documentation and marketing & publicity
13 * materials, and acknowledgment shall be given in the documentation, materials
14 * and software packages that this Software was used.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include <dbus/dbus.h>
30 #define ENABLE_INTROSPECTION 1
34 #define Dprintf(fmt...) if(EDebug(EDBUG_TYPE_DBUS))Eprintf(fmt)
35 #define D2printf(fmt...) if(EDebug(EDBUG_TYPE_DBUS)>1)Eprintf(fmt)
37 #define Dprintf(fmt...)
38 #define D2printf(fmt...)
48 static DbusData dbus_data;
50 static EventFdDesc *db_efd = NULL;
53 DbusWatchAdd(DBusWatch * watch, void *data __UNUSED__)
55 dbus_data.watch = watch;
56 dbus_data.fd = dbus_watch_get_unix_fd(watch);
58 D2printf("DbusWatchAdd fd=%d flags=%d\n", dbus_data.fd,
59 dbus_watch_get_flags(dbus_data.watch));
65 DbusWatchRemove(DBusWatch * watch __UNUSED__, void *data __UNUSED__)
67 D2printf("DbusWatchRemove\n");
70 #if 0 /* Don't need this */
72 DbusWatchToggle(DBusWatch * watch __UNUSED__, void *data __UNUSED__)
74 D2printf("DbusWatchToggle\n");
77 #define DbusWatchToggle NULL
81 DbusReplyString(DBusConnection * conn, DBusMessage * msg, const char *str)
86 reply = dbus_message_new_method_return(msg);
88 dbus_message_iter_init_append(reply, &args);
89 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &str))
91 if (!dbus_connection_send(conn, reply, NULL))
93 dbus_connection_flush(conn);
96 dbus_message_unref(reply);
100 DbusIpcReply(void *data, const char *str)
102 DBusMessage *msg = (DBusMessage *) data;
106 DbusReplyString(dbus_data.conn, msg, str);
110 DbusMethodCommand(DBusConnection * conn, DBusMessage * msg)
112 DBusMessageIter args;
113 const char *param = "";
115 if (!dbus_message_iter_init(msg, &args) ||
116 dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING)
118 DbusReplyString(conn, msg, "String arg required\n");
122 dbus_message_iter_get_basic(&args, ¶m);
124 IpcExecReply(param, DbusIpcReply, msg);
127 #if ENABLE_INTROSPECTION
129 static const char dbus_introspect_data[] =
130 "<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'\n"
131 "'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n"
133 " <interface name='org.freedesktop.DBus.Introspectable'>\n"
134 " <method name='Introspect'>\n"
135 " <arg name='data' direction='out' type='s'/>\n"
138 " <interface name='%s'>\n"
139 " <method name='Command'>\n"
140 " <arg name='data' direction='out' type='s'/>\n"
142 " <signal name='Signal'>\n"
143 " <arg name='data' direction='in' type='s'/>\n"
150 DbusMsgIntrospect(DBusConnection * conn, DBusMessage * msg)
154 D2printf("Introspect\n");
156 Esnprintf(buf, sizeof(buf), dbus_introspect_data, dbus_data.name);
157 if (!strcmp(dbus_message_get_path(msg), "/"))
158 DbusReplyString(conn, msg, buf);
160 DbusReplyString(conn, msg, "");
164 static DBusHandlerResult
165 DbusMsgHandler(DBusConnection * conn, DBusMessage * msg,
166 void *user_data __UNUSED__)
169 const char *msg_dest, *msg_ifc, *msg_memb;
171 D2printf("DbusMsgHandler\n");
173 msg_type = dbus_message_get_type(msg);
174 msg_dest = dbus_message_get_destination(msg);
175 msg_ifc = dbus_message_get_interface(msg);
176 msg_memb = dbus_message_get_member(msg);
180 default: /* Should not be possible */
181 Dprintf("MESSAGE type=%d\n", msg_type);
184 case DBUS_MESSAGE_TYPE_METHOD_CALL:
185 Dprintf("METHOD %s %s\n", msg_ifc, msg_memb);
186 if (strcmp(msg_dest, dbus_data.name))
188 if (!strcmp(msg_ifc, "org.e16"))
190 if (!strcmp(msg_memb, "Command"))
191 DbusMethodCommand(conn, msg);
193 DbusReplyString(conn, msg, "Error");
195 #if ENABLE_INTROSPECTION
196 else if (!strcmp(msg_ifc, "org.freedesktop.DBus.Introspectable"))
198 if (!strcmp(msg_memb, "Introspect"))
199 DbusMsgIntrospect(conn, msg);
204 case DBUS_MESSAGE_TYPE_SIGNAL:
205 Dprintf("SIGNAL %s %s\n", msg_ifc, msg_memb);
206 if (!strcmp(msg_ifc, "org.e16"))
208 Dprintf("... for me!\n");
213 D2printf("sender = %s\n", dbus_message_get_sender(msg));
214 D2printf("dest = %s\n", dbus_message_get_destination(msg));
215 D2printf("path = %s\n", dbus_message_get_path(msg));
216 D2printf("interface = %s\n", dbus_message_get_interface(msg));
217 D2printf("member = %s\n", dbus_message_get_member(msg));
219 return DBUS_HANDLER_RESULT_HANDLED;
227 D2printf("DbusHandleFd flags=%d\n", dbus_watch_get_flags(dbus_data.watch));
228 dbus_watch_handle(dbus_data.watch,
229 DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE);
233 D2printf("DbusHandleFd: Dispatch flags=%d\n",
234 dbus_watch_get_flags(dbus_data.watch));
235 rc = dbus_connection_dispatch(dbus_data.conn);
236 if (rc == DBUS_DISPATCH_COMPLETE)
250 sprintf(buf, "org.e16.wm.p%u", (unsigned int)Mode.wm.pid);
256 s = strchr(Dpy.name, ':');
259 sprintf(buf, "org.e16.wm.d%ds%d", atoi(s + 1), Dpy.screen);
261 dbus_data.name = Estrdup(buf);
262 Esetenv("ENL_DBUS_NAME", dbus_data.name);
264 dbus_error_init(&dberr);
268 dbus_data.conn = dbus_bus_get(DBUS_BUS_SESSION, &dberr);
269 if (dbus_error_is_set(&dberr))
271 dbus_connection_set_exit_on_disconnect(dbus_data.conn, FALSE);
273 err = dbus_bus_request_name(dbus_data.conn, dbus_data.name,
274 DBUS_NAME_FLAG_DO_NOT_QUEUE, &dberr);
275 if (dbus_error_is_set(&dberr))
277 if (err != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
279 Eprintf("*** DbusInit error: Not Primary Owner (%d)\n", err);
283 Esnprintf(buf, sizeof(buf), "type='signal',destination='%s'",
285 if (EDebug(EDBUG_TYPE_DBUS) > 1) /* Catch all signals if extra debug is enabled */
286 dbus_bus_add_match(dbus_data.conn, "type='signal'", &dberr);
288 dbus_bus_add_match(dbus_data.conn, buf, &dberr);
289 if (dbus_error_is_set(&dberr))
291 Esnprintf(buf, sizeof(buf), "type='method_call',destination='%s'",
293 dbus_bus_add_match(dbus_data.conn, buf, &dberr);
294 if (dbus_error_is_set(&dberr))
297 dbus_bus_add_match(dbus_data.conn, "type='method_return'", &dberr);
298 if (dbus_error_is_set(&dberr))
300 dbus_bus_add_match(dbus_data.conn, "type='error'", &dberr);
301 if (dbus_error_is_set(&dberr))
305 if (!dbus_connection_add_filter(dbus_data.conn, DbusMsgHandler, NULL, NULL))
308 err = dbus_connection_set_watch_functions(dbus_data.conn,
309 DbusWatchAdd, DbusWatchRemove,
310 DbusWatchToggle, NULL, NULL);
312 /* Handle pending D-Bus stuff */
314 db_efd = EventFdRegister(dbus_data.fd, DbusHandleFd);
318 if (dbus_error_is_set(&dberr))
320 Eprintf("*** DbusInit error: %s\n", dberr.message);
321 dbus_error_free(&dberr);