gdbus: Add support for creating D-Bus proxies without object manager

This commit is contained in:
Marcel Holtmann 2012-12-27 21:19:31 -08:00
parent d1bd840d2e
commit 8bef871cff
2 changed files with 147 additions and 62 deletions

View File

@ -198,6 +198,128 @@ static void prop_entry_free(gpointer data)
g_free(prop);
}
static void add_property(GDBusProxy *proxy, const char *name,
DBusMessageIter *iter)
{
DBusMessageIter value;
struct prop_entry *prop;
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
return;
dbus_message_iter_recurse(iter, &value);
prop = g_hash_table_lookup(proxy->prop_list, name);
if (prop != NULL) {
GDBusClient *client = proxy->client;
prop_entry_update(prop, &value);
if (client == NULL)
return;
if (client->property_changed)
client->property_changed(proxy, name, &value,
client->user_data);
return;
}
prop = prop_entry_new(name, &value);
if (prop == NULL)
return;
g_hash_table_replace(proxy->prop_list, prop->name, prop);
}
static void update_properties(GDBusProxy *proxy, DBusMessageIter *iter)
{
DBusMessageIter dict;
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return;
dbus_message_iter_recurse(iter, &dict);
while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
DBusMessageIter entry;
const char *name;
dbus_message_iter_recurse(&dict, &entry);
if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
break;
dbus_message_iter_get_basic(&entry, &name);
dbus_message_iter_next(&entry);
add_property(proxy, name, &entry);
dbus_message_iter_next(&dict);
}
}
static void get_all_properties_reply(DBusPendingCall *call, void *user_data)
{
GDBusProxy *proxy = user_data;
DBusMessage *reply = dbus_pending_call_steal_reply(call);
DBusMessageIter iter;
DBusError error;
dbus_error_init(&error);
if (dbus_set_error_from_message(&error, reply) == TRUE) {
dbus_error_free(&error);
goto done;
}
dbus_message_iter_init(reply, &iter);
update_properties(proxy, &iter);
done:
if (proxy->client != NULL) {
GDBusClient *client = proxy->client;
if (client->proxy_added)
client->proxy_added(proxy, client->user_data);
client->proxy_list = g_list_append(client->proxy_list, proxy);
} else
g_dbus_proxy_unref(proxy);
dbus_message_unref(reply);
}
static void get_all_properties(GDBusProxy *proxy)
{
GDBusClient *client = proxy->client;
const char *service_name = client->service_name;
DBusMessage *msg;
DBusPendingCall *call;
msg = dbus_message_new_method_call(service_name, proxy->obj_path,
DBUS_INTERFACE_PROPERTIES, "GetAll");
if (msg == NULL)
return;
dbus_message_append_args(msg, DBUS_TYPE_STRING, &proxy->interface,
DBUS_TYPE_INVALID);
if (dbus_connection_send_with_reply(client->dbus_conn, msg,
&call, -1) == FALSE) {
dbus_message_unref(msg);
return;
}
g_dbus_proxy_ref(proxy);
dbus_pending_call_set_notify(call, get_all_properties_reply,
proxy, NULL);
dbus_pending_call_unref(call);
dbus_message_unref(msg);
}
static GDBusProxy *proxy_lookup(GDBusClient *client, const char *path,
const char *interface)
{
@ -285,6 +407,27 @@ static void proxy_remove(GDBusClient *client, const char *path,
}
}
GDBusProxy *g_dbus_proxy_new(GDBusClient *client, const char *path,
const char *interface)
{
GDBusProxy *proxy;
if (client == NULL)
return NULL;
proxy = proxy_lookup(client, path, interface);
if (proxy)
return g_dbus_proxy_ref(proxy);
proxy = proxy_new(client, path, interface);
if (proxy == NULL)
return NULL;
get_all_properties(proxy);
return proxy;
}
GDBusProxy *g_dbus_proxy_ref(GDBusProxy *proxy)
{
if (proxy == NULL)
@ -514,66 +657,6 @@ gboolean g_dbus_proxy_method_call(GDBusProxy *proxy, const char *method,
return TRUE;
}
static void add_property(GDBusProxy *proxy, const char *name,
DBusMessageIter *iter)
{
DBusMessageIter value;
struct prop_entry *prop;
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
return;
dbus_message_iter_recurse(iter, &value);
prop = g_hash_table_lookup(proxy->prop_list, name);
if (prop != NULL) {
GDBusClient *client = proxy->client;
prop_entry_update(prop, &value);
if (client == NULL)
return;
if (client->property_changed)
client->property_changed(proxy, name, &value,
client->user_data);
return;
}
prop = prop_entry_new(name, &value);
if (prop == NULL)
return;
g_hash_table_replace(proxy->prop_list, prop->name, prop);
}
static void update_properties(GDBusProxy *proxy, DBusMessageIter *iter)
{
DBusMessageIter dict;
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return;
dbus_message_iter_recurse(iter, &dict);
while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
DBusMessageIter entry;
const char *name;
dbus_message_iter_recurse(&dict, &entry);
if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
break;
dbus_message_iter_get_basic(&entry, &name);
dbus_message_iter_next(&entry);
add_property(proxy, name, &entry);
dbus_message_iter_next(&dict);
}
}
static void properties_changed(GDBusClient *client, const char *path,
DBusMessage *msg)
{

View File

@ -274,8 +274,12 @@ gboolean g_dbus_get_properties(DBusConnection *connection, const char *path,
gboolean g_dbus_attach_object_manager(DBusConnection *connection);
gboolean g_dbus_detach_object_manager(DBusConnection *connection);
typedef struct GDBusClient GDBusClient;
typedef struct GDBusProxy GDBusProxy;
GDBusProxy *g_dbus_proxy_new(GDBusClient *client, const char *path,
const char *interface);
GDBusProxy *g_dbus_proxy_ref(GDBusProxy *proxy);
void g_dbus_proxy_unref(GDBusProxy *proxy);
@ -300,8 +304,6 @@ gboolean g_dbus_proxy_method_call(GDBusProxy *proxy, const char *method,
GDBusReturnFunction function, void *user_data,
GDBusDestroyFunction destroy);
typedef struct GDBusClient GDBusClient;
GDBusClient *g_dbus_client_new(DBusConnection *connection,
const char *service, const char *path);