2 * dbus.c - awesome dbus support
4 * Copyright © 2008 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <dbus/dbus.h>
35 extern awesome_t globalconf
;
38 static DBusConnection
*dbus_connection
= NULL
;
39 ev_io dbusio
= { .fd
= -1 };
42 a_dbus_message_iter(DBusMessageIter
*iter
)
48 switch(dbus_message_iter_get_arg_type(iter
))
50 case DBUS_TYPE_INVALID
:
52 case DBUS_TYPE_VARIANT
:
54 DBusMessageIter subiter
;
55 dbus_message_iter_recurse(iter
, &subiter
);
56 a_dbus_message_iter(&subiter
);
60 case DBUS_TYPE_DICT_ENTRY
:
62 DBusMessageIter subiter
;
64 /* initialize a sub iterator */
65 dbus_message_iter_recurse(iter
, &subiter
);
66 /* create a new table to store the dict */
67 a_dbus_message_iter(&subiter
);
73 int array_type
= dbus_message_iter_get_element_type(iter
);
75 /* create a new table to store all the value */
76 lua_newtable(globalconf
.L
);
78 if(dbus_type_is_fixed(array_type
))
82 #define DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(type, dbustype) \
86 dbus_message_iter_get_fixed_array(iter, &data, &datalen); \
87 for(int i = 0; i < datalen; i++) \
89 lua_pushnumber(globalconf.L, data[i]); \
90 lua_rawseti(globalconf.L, -2, i + 1); \
94 DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(int16_t, DBUS_TYPE_INT16
)
95 DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(uint16_t, DBUS_TYPE_UINT16
)
96 DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(int32_t, DBUS_TYPE_INT32
)
97 DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(uint32_t, DBUS_TYPE_UINT32
)
98 DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(int64_t, DBUS_TYPE_INT64
)
99 DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER(uint64_t, DBUS_TYPE_UINT64
)
100 #undef DBUS_MSG_HANDLE_ARRAY_TYPE_NUMBER
102 else if(array_type
== DBUS_TYPE_DICT_ENTRY
)
104 DBusMessageIter subiter
;
106 /* initialize a sub iterator */
107 dbus_message_iter_recurse(iter
, &subiter
);
108 /* get the keys and the values
109 * n is the number of entry in * dict */
110 int n
= a_dbus_message_iter(&subiter
);
112 for(int i
= 0; i
< n
; i
++)
113 lua_rawset(globalconf
.L
, - (n
* 2) - 1 + i
* 2);
117 DBusMessageIter subiter
;
119 /* prepare to dig into the array*/
120 dbus_message_iter_recurse(iter
, &subiter
);
122 /* now iterate over every element of the array */
123 int n
= a_dbus_message_iter(&subiter
);
125 for(int i
= n
; i
> 0; i
--)
127 lua_rawseti(globalconf
.L
, - i
- 1, i
);
133 case DBUS_TYPE_BOOLEAN
:
136 dbus_message_iter_get_basic(iter
, &b
);
137 lua_pushboolean(globalconf
.L
, b
);
144 dbus_message_iter_get_basic(iter
, &c
);
145 lua_pushlstring(globalconf
.L
, &c
, 1);
149 #define DBUS_MSG_HANDLE_TYPE_NUMBER(type, dbustype) \
153 dbus_message_iter_get_basic(iter, &ui); \
154 lua_pushnumber(globalconf.L, ui); \
158 DBUS_MSG_HANDLE_TYPE_NUMBER(int16_t, DBUS_TYPE_INT16
)
159 DBUS_MSG_HANDLE_TYPE_NUMBER(uint16_t, DBUS_TYPE_UINT16
)
160 DBUS_MSG_HANDLE_TYPE_NUMBER(int32_t, DBUS_TYPE_INT32
)
161 DBUS_MSG_HANDLE_TYPE_NUMBER(uint32_t, DBUS_TYPE_UINT32
)
162 DBUS_MSG_HANDLE_TYPE_NUMBER(int64_t, DBUS_TYPE_INT64
)
163 DBUS_MSG_HANDLE_TYPE_NUMBER(uint64_t, DBUS_TYPE_UINT64
)
164 #undef DBUS_MSG_HANDLE_TYPE_NUMBER
165 case DBUS_TYPE_STRING
:
168 dbus_message_iter_get_basic(iter
, &s
);
169 lua_pushstring(globalconf
.L
, s
);
174 } while(dbus_message_iter_next(iter
));
180 a_dbus_process_request(DBusMessage
*msg
)
182 if(globalconf
.hooks
.dbus
== LUA_REFNIL
)
185 lua_newtable(globalconf
.L
);
187 switch(dbus_message_get_type(msg
))
189 case DBUS_MESSAGE_TYPE_SIGNAL
:
190 lua_pushliteral(globalconf
.L
, "signal");
192 case DBUS_MESSAGE_TYPE_METHOD_CALL
:
193 lua_pushliteral(globalconf
.L
, "method_call");
195 case DBUS_MESSAGE_TYPE_METHOD_RETURN
:
196 lua_pushliteral(globalconf
.L
, "method_return");
198 case DBUS_MESSAGE_TYPE_ERROR
:
199 lua_pushliteral(globalconf
.L
, "error");
202 lua_pushliteral(globalconf
.L
, "unknown");
206 lua_setfield(globalconf
.L
, -2, "type");
208 const char *s
= dbus_message_get_interface(msg
);
209 lua_pushstring(globalconf
.L
, NONULL(s
));
210 lua_setfield(globalconf
.L
, -2, "interface");
212 s
= dbus_message_get_path(msg
);
213 lua_pushstring(globalconf
.L
, NONULL(s
));
214 lua_setfield(globalconf
.L
, -2, "path");
216 s
= dbus_message_get_member(msg
);
217 lua_pushstring(globalconf
.L
, NONULL(s
));
218 lua_setfield(globalconf
.L
, -2, "member");
220 /* + 1 for the table above */
221 DBusMessageIter iter
;
224 if(dbus_message_iter_init(msg
, &iter
))
225 nargs
+= a_dbus_message_iter(&iter
);
227 if(dbus_message_get_no_reply(msg
))
228 luaA_dofunction(globalconf
.L
, globalconf
.hooks
.dbus
, nargs
, 0);
231 int n
= lua_gettop(globalconf
.L
) - nargs
;
232 luaA_dofunction(globalconf
.L
, globalconf
.hooks
.dbus
, nargs
, LUA_MULTRET
);
233 n
-= lua_gettop(globalconf
.L
);
235 DBusMessage
*reply
= dbus_message_new_method_return(msg
);
237 dbus_message_iter_init_append(reply
, &iter
);
240 for(int i
= n
; i
< 0; i
+= 2)
242 /* i is the type name, i+1 the value */
244 const char *type
= lua_tolstring(globalconf
.L
, i
, &len
);
246 if(!type
|| len
!= 1)
251 case DBUS_TYPE_BOOLEAN
:
253 bool b
= lua_toboolean(globalconf
.L
, i
+ 1);
254 dbus_message_iter_append_basic(&iter
, DBUS_TYPE_BOOLEAN
, &b
);
257 #define DBUS_MSG_RETURN_HANDLE_TYPE_STRING(dbustype) \
259 if((s = lua_tostring(globalconf.L, i + 1))) \
260 dbus_message_iter_append_basic(&iter, dbustype, &s); \
262 DBUS_MSG_RETURN_HANDLE_TYPE_STRING(DBUS_TYPE_STRING
)
263 DBUS_MSG_RETURN_HANDLE_TYPE_STRING(DBUS_TYPE_BYTE
)
264 #undef DBUS_MSG_RETURN_HANDLE_TYPE_STRING
265 #define DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(type, dbustype) \
268 type num = lua_tonumber(globalconf.L, i + 1); \
269 dbus_message_iter_append_basic(&iter, dbustype, &num); \
272 DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(int16_t, DBUS_TYPE_INT16
)
273 DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(uint16_t, DBUS_TYPE_UINT16
)
274 DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(int32_t, DBUS_TYPE_INT32
)
275 DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(uint32_t, DBUS_TYPE_UINT32
)
276 DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(int64_t, DBUS_TYPE_INT64
)
277 DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(uint64_t, DBUS_TYPE_UINT64
)
278 DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER(double, DBUS_TYPE_DOUBLE
)
279 #undef DBUS_MSG_RETURN_HANDLE_TYPE_NUMBER
282 lua_remove(globalconf
.L
, i
);
283 lua_remove(globalconf
.L
, i
+ 1);
286 dbus_connection_send(dbus_connection
, reply
, NULL
);
287 dbus_message_unref(reply
);
292 a_dbus_process_requests(EV_P_ ev_io
*w
, int revents
)
297 if(!dbus_connection
&& !a_dbus_init())
302 dbus_connection_read_write(dbus_connection
, 0);
304 if(!(msg
= dbus_connection_pop_message(dbus_connection
)))
307 if(dbus_message_is_signal(msg
, DBUS_INTERFACE_LOCAL
, "Disconnected"))
310 dbus_message_unref(msg
);
314 a_dbus_process_request(msg
);
316 dbus_message_unref(msg
);
322 dbus_connection_flush(dbus_connection
);
326 a_dbus_request_name(const char *name
)
328 int ret
= dbus_bus_request_name(dbus_connection
, name
, 0, &err
);
330 if(dbus_error_is_set(&err
))
332 warn("failed to request D-Bus name: %s", err
.message
);
338 case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
:
340 case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER
:
341 warn("already primary D-Bus name owner for %s", name
);
348 a_dbus_release_name(const char *name
)
350 int ret
= dbus_bus_release_name(dbus_connection
, name
, &err
);
352 if(dbus_error_is_set(&err
))
354 warn("failed to release D-Bus name: %s", err
.message
);
360 case DBUS_RELEASE_NAME_REPLY_NOT_OWNER
:
361 warn("not primary D-Bus name owner for %s", name
);
363 case DBUS_RELEASE_NAME_REPLY_NON_EXISTENT
:
364 warn("non existent D-Bus name: %s", name
);
375 dbus_error_init(&err
);
377 dbus_connection
= dbus_bus_get(DBUS_BUS_SESSION
, &err
);
378 if(dbus_error_is_set(&err
))
380 warn("D-Bus system bus connection failed: %s", err
.message
);
381 dbus_connection
= NULL
;
382 dbus_error_free(&err
);
386 dbus_connection_set_exit_on_disconnect(dbus_connection
, FALSE
);
388 a_dbus_request_name("org.awesome");
390 if(!dbus_connection_get_unix_fd(dbus_connection
, &fd
))
392 warn("cannot get D-Bus connection file descriptor");
397 fcntl(fd
, F_SETFD
, FD_CLOEXEC
);
399 ev_io_init(&dbusio
, a_dbus_process_requests
, fd
, EV_READ
);
400 ev_io_start(EV_DEFAULT_UC_
&dbusio
);
401 ev_unref(EV_DEFAULT_UC
);
411 dbus_error_free(&err
);
413 if (dbusio
.fd
>= 0) {
414 ev_ref(EV_DEFAULT_UC
);
415 ev_io_stop(EV_DEFAULT_UC_
&dbusio
);
419 /* This is a shared connection owned by libdbus
420 * Do not close it, only unref
422 dbus_connection_unref(dbus_connection
);
423 dbus_connection
= NULL
;
426 /** Register a D-Bus name to receive message from.
427 * \param L The Lua VM state.
428 * \return The number of elements pushed on stack.
430 * \lparam A string with the name of the D-Bus name to register. Note that
431 * org.awesome is registered by default.
432 * \lreturn True if everything worked fine, false otherwise.
435 luaA_dbus_request_name(lua_State
*L
)
437 const char *name
= luaL_checkstring(L
, 1);
438 lua_pushboolean(L
, a_dbus_request_name(name
));
442 /** Release a D-Bus name.
443 * \param L The Lua VM state.
444 * \return The number of elements pushed on stack.
446 * \lparam A string with the name of the D-Bus name to unregister.
447 * \lreturn True if everything worked fine, false otherwise.
450 luaA_dbus_release_name(lua_State
*L
)
452 const char *name
= luaL_checkstring(L
, 1);
453 lua_pushboolean(L
, a_dbus_release_name(name
));
457 /** Add a match rule to match messages going through the message bus.
458 * \param L The Lua VM state.
459 * \return The number of elements pushed on stack.
461 * \lparam A string with the name of the match rule.
464 luaA_dbus_add_match(lua_State
*L
)
466 const char *name
= luaL_checkstring(L
, 1);
467 dbus_bus_add_match(dbus_connection
, name
, NULL
);
468 dbus_connection_flush(dbus_connection
);
472 /** Remove a previously added match rule "by value"
473 * (the most recently-added identical rule gets removed).
474 * \param L The Lua VM state.
475 * \return The number of elements pushed on stack.
477 * \lparam A string with the name of the match rule.
480 luaA_dbus_remove_match(lua_State
*L
)
482 const char *name
= luaL_checkstring(L
, 1);
483 dbus_bus_remove_match(dbus_connection
, name
, NULL
);
484 dbus_connection_flush(dbus_connection
);
488 const struct luaL_reg awesome_dbus_lib
[] =
490 { "request_name", luaA_dbus_request_name
},
491 { "release_name", luaA_dbus_release_name
},
492 { "add_match", luaA_dbus_add_match
},
493 { "remove_match", luaA_dbus_remove_match
},
497 #else /* HAVE_DBUS */
512 luaA_donothing(lua_State
*L
)
517 const struct luaL_reg awesome_dbus_lib
[] =
519 { "request_name", luaA_donothing
},
520 { "release_name", luaA_donothing
},
521 { "add_match", luaA_donothing
},
522 { "remove_match", luaA_donothing
},
527 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80