DBus:当名字从公共汽车上消失时观察

时间:2017-04-22 00:48:24

标签: c dbus

我使用低级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服务名称,我如何知道该名称何时从公共汽车上消失?

2 个答案:

答案 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()