#include #include #define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties" /* ---------------------------------------------------------------------------------------------------- */ /* The object we want to export */ typedef struct _MyObjectClass MyObjectClass; typedef struct _MyObject MyObject; struct _MyObjectClass { GObjectClass parent_class; }; struct _MyObject { GObject parent_instance; gint count; gchar *name; }; enum { PROP_0, PROP_COUNT, PROP_NAME }; static GType my_object_get_type (void); G_DEFINE_TYPE (MyObject, my_object, G_TYPE_OBJECT) static void my_object_finalize (GObject *object) { MyObject *myobj = (MyObject*)object; g_free (myobj->name); G_OBJECT_CLASS (my_object_parent_class)->finalize (object); } static void my_object_init (MyObject *object) { object->count = 0; object->name = NULL; } static void my_object_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { MyObject *myobj = (MyObject*)object; switch (prop_id) { case PROP_COUNT: g_value_set_int (value, myobj->count); break; case PROP_NAME: g_value_set_string (value, myobj->name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void my_object_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { MyObject *myobj = (MyObject*)object; switch (prop_id) { case PROP_COUNT: myobj->count = g_value_get_int (value); break; case PROP_NAME: g_free (myobj->name); myobj->name = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void my_object_class_init (MyObjectClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS (class); gobject_class->finalize = my_object_finalize; gobject_class->set_property = my_object_set_property; gobject_class->get_property = my_object_get_property; g_object_class_install_property (gobject_class, PROP_COUNT, g_param_spec_int ("count", "Count", "Count", 0, 99999, 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_NAME, g_param_spec_string ("name", "Name", "Name", NULL, G_PARAM_READWRITE)); } /* A method that we want to export */ static void my_object_change_count (MyObject *myobj, gint change) { myobj->count = 2 * myobj->count + change; g_object_notify (G_OBJECT (myobj), "count"); } /* ---------------------------------------------------------------------------------------------------- */ static GDBusNodeInfo *introspection_data = NULL; /* Introspection data for the service we are exporting */ static const gchar introspection_xml[] = "" " " " " " " " " " " " " " " ""; static void handle_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { MyObject *myobj = user_data; if (g_strcmp0 (method_name, "ChangeCount") == 0) { gint change; g_variant_get (parameters, "(i)", &change); my_object_change_count (myobj, change); g_dbus_method_invocation_return_value (invocation, NULL); } } static GVariant * handle_get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data) { GVariant *ret; MyObject *myobj = user_data; ret = NULL; if (g_strcmp0 (property_name, "Count") == 0) { ret = g_variant_new_int32 (myobj->count); } else if (g_strcmp0 (property_name, "Name") == 0) { ret = g_variant_new_string (myobj->name ? myobj->name : ""); } return ret; } static gboolean handle_set_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *value, GError **error, gpointer user_data) { MyObject *myobj = user_data; if (g_strcmp0 (property_name, "Count") == 0) { g_object_set (myobj, "count", g_variant_get_int32 (value), NULL); } else if (g_strcmp0 (property_name, "Name") == 0) { g_object_set (myobj, "name", g_variant_get_string (value, NULL), NULL); } return TRUE; } /* for now */ static const GDBusInterfaceVTable interface_vtable = { handle_method_call, handle_get_property, handle_set_property, { 0 } }; static void send_property_change (GObject *obj, GParamSpec *pspec, GDBusConnection *connection) { GVariantBuilder *builder; GVariantBuilder *invalidated_builder; MyObject *myobj = (MyObject *)obj; builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY); invalidated_builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); if (g_strcmp0 (pspec->name, "count") == 0) g_variant_builder_add (builder, "{sv}", "Count", g_variant_new_int32 (myobj->count)); else if (g_strcmp0 (pspec->name, "name") == 0) g_variant_builder_add (builder, "{sv}", "Name", g_variant_new_string (myobj->name ? myobj->name : "")); g_dbus_connection_emit_signal (connection, NULL, "/org/myorg/MyObject", DBUS_INTERFACE_PROPERTIES, "PropertiesChanged", g_variant_new ("(sa{sv}as)", "org.myorg.MyObject", builder, invalidated_builder), NULL); } static void on_bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data) { MyObject *myobj = user_data; guint registration_id; g_signal_connect (myobj, "notify", G_CALLBACK (send_property_change), connection); registration_id = g_dbus_connection_register_object (connection, "/org/myorg/MyObject", introspection_data->interfaces[0], &interface_vtable, myobj, NULL, /* user_data_free_func */ NULL); /* GError** */ g_assert (registration_id > 0); } static void on_name_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data) { } static void on_name_lost (GDBusConnection *connection, const gchar *name, gpointer user_data) { exit (1); } int main (int argc, char *argv[]) { guint owner_id; GMainLoop *loop; MyObject *myobj; /* We are lazy here - we don't want to manually provide * the introspection data structures - so we just build * them from XML. */ introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); g_assert (introspection_data != NULL); myobj = g_object_new (my_object_get_type (), NULL); owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, "org.myorg.MyObject", G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired, on_name_acquired, on_name_lost, myobj, NULL); loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (loop); g_bus_unown_name (owner_id); g_dbus_node_info_unref (introspection_data); g_object_unref (myobj); return 0; }