#include #include #include /* ---------------------------------------------------------------------------------------------------- */ static GDBusNodeInfo *introspection_data = NULL; static const GDBusInterfaceInfo *manager_interface_info = NULL; static const GDBusInterfaceInfo *block_interface_info = NULL; static const GDBusInterfaceInfo *partition_interface_info = NULL; /* Introspection data for the service we are exporting */ static const gchar introspection_xml[] = "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ""; /* ---------------------------------------------------------------------------------------------------- */ static void manager_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) { const gchar *greeting; gchar *response; g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.Example.Manager"); g_assert_cmpstr (method_name, ==, "Hello"); g_variant_get (parameters, "(s)", &greeting); response = g_strdup_printf ("Method %s.%s with user_data `%s' on object path %s called with arg '%s'", interface_name, method_name, (const gchar *) user_data, object_path, greeting); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", response)); g_free (response); } const GDBusInterfaceVTable manager_vtable = { manager_method_call, NULL, /* get_property */ NULL /* set_property */ }; /* ---------------------------------------------------------------------------------------------------- */ static void block_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) { g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.Example.Block"); if (g_strcmp0 (method_name, "Hello") == 0) { const gchar *greeting; gchar *response; g_variant_get (parameters, "(s)", &greeting); response = g_strdup_printf ("Method %s.%s with user_data `%s' on object path %s called with arg '%s'", interface_name, method_name, (const gchar *) user_data, object_path, greeting); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", response)); g_free (response); } else if (g_strcmp0 (method_name, "DoStuff") == 0) { g_dbus_method_invocation_return_dbus_error (invocation, "org.gtk.GDBus.TestSubtree.Error.Failed", "This method intentionally always fails"); } else { g_assert_not_reached (); } } static GVariant * block_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; const gchar *node; gint major; gint minor; node = strrchr (object_path, '/') + 1; if (g_str_has_prefix (node, "sda")) major = 8; else major = 9; if (strlen (node) == 4) minor = node[3] - '0'; else minor = 0; ret = NULL; if (g_strcmp0 (property_name, "Major") == 0) { ret = g_variant_new_int32 (major); } else if (g_strcmp0 (property_name, "Minor") == 0) { ret = g_variant_new_int32 (minor); } else if (g_strcmp0 (property_name, "Notes") == 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Hello %s. I thought I said reading this property " "always results in an error. kthxbye", sender); } else { g_assert_not_reached (); } return ret; } static gboolean block_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) { /* TODO */ g_assert_not_reached (); } const GDBusInterfaceVTable block_vtable = { block_method_call, block_get_property, block_set_property, }; /* ---------------------------------------------------------------------------------------------------- */ static void partition_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) { const gchar *greeting; gchar *response; g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.Example.Partition"); g_assert_cmpstr (method_name, ==, "Hello"); g_variant_get (parameters, "(s)", &greeting); response = g_strdup_printf ("Method %s.%s with user_data `%s' on object path %s called with arg '%s'", interface_name, method_name, (const gchar *) user_data, object_path, greeting); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", response)); g_free (response); } const GDBusInterfaceVTable partition_vtable = { partition_method_call, //partition_get_property, //partition_set_property }; /* ---------------------------------------------------------------------------------------------------- */ static gchar ** subtree_enumerate (GDBusConnection *connection, const gchar *sender, const gchar *object_path, gpointer user_data) { gchar **nodes; GPtrArray *p; p = g_ptr_array_new (); g_ptr_array_add (p, g_strdup ("sda")); g_ptr_array_add (p, g_strdup ("sda1")); g_ptr_array_add (p, g_strdup ("sda2")); g_ptr_array_add (p, g_strdup ("sda3")); g_ptr_array_add (p, g_strdup ("sdb")); g_ptr_array_add (p, g_strdup ("sdb1")); g_ptr_array_add (p, g_strdup ("sdc")); g_ptr_array_add (p, g_strdup ("sdc1")); g_ptr_array_add (p, NULL); nodes = (gchar **) g_ptr_array_free (p, FALSE); return nodes; } static GPtrArray * subtree_introspect (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *node, gpointer user_data) { GPtrArray *p; p = g_ptr_array_new (); if (g_strcmp0 (node, "/") == 0) { g_ptr_array_add (p, (gpointer) manager_interface_info); } else { g_ptr_array_add (p, (gpointer) block_interface_info); if (strlen (node) == 4) g_ptr_array_add (p, (gpointer) partition_interface_info); } return p; } static const GDBusInterfaceVTable * subtree_dispatch (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *node, gpointer *out_user_data, gpointer user_data) { const GDBusInterfaceVTable *vtable_to_return; gpointer user_data_to_return; if (g_strcmp0 (interface_name, "org.gtk.GDBus.Example.Manager") == 0) { user_data_to_return = "The Root"; vtable_to_return = &manager_vtable; } else { if (strlen (node) == 4) user_data_to_return = "A partition"; else user_data_to_return = "A block device"; if (g_strcmp0 (interface_name, "org.gtk.GDBus.Example.Block") == 0) vtable_to_return = &block_vtable; else if (g_strcmp0 (interface_name, "org.gtk.GDBus.Example.Partition") == 0) vtable_to_return = &partition_vtable; else g_assert_not_reached (); } *out_user_data = user_data_to_return; return vtable_to_return; } const GDBusSubtreeVTable subtree_vtable = { subtree_enumerate, subtree_introspect, subtree_dispatch }; /* ---------------------------------------------------------------------------------------------------- */ static void on_bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data) { guint registration_id; registration_id = g_dbus_connection_register_subtree (connection, "/org/gtk/GDBus/TestSubtree/Devices", &subtree_vtable, G_DBUS_SUBTREE_FLAGS_NONE, NULL, /* user_data */ 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; g_type_init (); /* 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); manager_interface_info = g_dbus_node_info_lookup_interface (introspection_data, "org.gtk.GDBus.Example.Manager"); block_interface_info = g_dbus_node_info_lookup_interface (introspection_data, "org.gtk.GDBus.Example.Block"); partition_interface_info = g_dbus_node_info_lookup_interface (introspection_data, "org.gtk.GDBus.Example.Partition"); g_assert (manager_interface_info != NULL); g_assert (block_interface_info != NULL); g_assert (partition_interface_info != NULL); owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, "org.gtk.GDBus.TestSubtree", G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired, on_name_acquired, on_name_lost, NULL, 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); return 0; }