我使用低级DBus C库来表达StatusNotifierWatcher服务。 StatusNotifierWatcher规范要求观察者知道"一个StatusNotifierItem实例何时从总线中消失了#34;这样它就可以发送StatusNotifierItemUnregistered
信号。
示例意图:
#include <stdio.h>
#include <stdlib.h>
#include <dbus/dbus.h>
DBusConnection *conn = NULL;
void item_unregistered_signal(const char *name) {
DBusMessage *signal = dbus_message_new_signal(
"/org/freedesktop/StatusNotifierWatcher",
"org.freedesktop.StatusNotifierWatcher",
"StatusNotifierItemUnregistered");
dbus_message_append_args(signal,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID);
dbus_connection_send(conn, signal, NULL);
dbus_message_unref(signal);
}
void watch_name(const char *name, void(*cb)(const char *)) {
// Not sure how to impliment
}
dbus_bool_t register_item(DBusConnection *connection, DBusMessage *message, void *_data) {
DBusError error;
char *name;
if (!dbus_message_get_args(message, &error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID)) {
fprintf(stderr, "Error parsing method args: %s\n", error.message);
return FALSE;
}
watch_name(name, item_unregistered_signal);
return TRUE;
}
static void check_and_abort(DBusError *error) {
if (dbus_error_is_set(error)) {
fprintf(stderr, "dbus_err: %s\n", error->message);
exit(EXIT_FAILURE);
}
}
int main() {
DBusError error;
dbus_error_init(&error);
conn = dbus_bus_get(DBUS_BUS_SESSION, &error);
check_and_abort(&error);
dbus_bus_request_name(conn, "org.freedesktop.StatusNotifierWatcher",
DBUS_NAME_FLAG_REPLACE_EXISTING,
&error);
check_and_abort(&error);
dbus_connection_add_filter(conn, register_item, NULL, free);
while(1) {
dbus_connection_read_write_dispatch(conn, 1000);
}
}
如果我有一个众所周知的DBus服务名称,我如何知道该名称何时从公共汽车上消失?
答案 0 :(得分:1)
好吧,我想出来了,我会为任何需要使用libdbus的未来可怜的灵魂发布答案。
每当任何DBus名称更改时, org.freedesktop.DBus
都会发送NameOwnerChanged
信号。可以使用此信号来跟踪项目是否已消失,因为NewOwner参数是空字符串。
这个功能可以做到:
static DBusHandlerResult signal_handler(DBusConnection *connection,
DBusMessage *message, void *_usr_data) {
if (dbus_message_is_signal(message, "org.freedesktop.DBus",
"NameOwnerChanged")) {
const char *name;
const char *old_owner;
const char *new_owner;
if (!dbus_message_get_args(message, NULL,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_STRING, &old_owner,
DBUS_TYPE_STRING, &new_owner,
DBUS_TYPE_INVALID)) {
fprintf(stderr, "Error getting OwnerChanged args");
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
if (strcmp(name, "") != 0) {
// Name not lost, just swapped owners
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
name_lost(name);
return DBUS_HANDLER_RESULT_HANDLED;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
还需要添加一个匹配项,以便使用此信号调用您的程序。我在main()
dbus_bus_add_match(conn,
"type='signal',\
sender='org.freedesktop.DBus',\
interface='org.freedesktop.DBus',\
member='NameOwnerChanged'",
&error);
check_and_abort(&error);
dbus_connection_add_filter(conn, signal_handler, NULL, free);
答案 1 :(得分:0)
对于那些使用GDBus(推荐)而不是libdbus(不鼓励)的人,相当于g_bus_watch_name()
。