summaryrefslogtreecommitdiff
path: root/src/lib/manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/manager.c')
-rw-r--r--src/lib/manager.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/lib/manager.c b/src/lib/manager.c
new file mode 100644
index 0000000..5286a3a
--- /dev/null
+++ b/src/lib/manager.c
@@ -0,0 +1,276 @@
+#include <gio/gio.h>
+#include "bluez-api.h"
+#include "dbus-common.h"
+#include "manager.h"
+
+struct _ManagerPrivate
+{
+ GDBusProxy *proxy;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE(Manager, manager, G_TYPE_OBJECT)
+
+static void manager_dispose (GObject *gobject)
+{
+ Manager *self = MANAGER (gobject);
+
+ /* In dispose(), you are supposed to free all types referenced from this
+ * object which might themselves hold a reference to self. Generally,
+ * the most simple solution is to unref all members on which you own a
+ * reference.
+ */
+
+ /* dispose() might be called multiple times, so we must guard against
+ * calling g_object_unref() on an invalid GObject by setting the member
+ * NULL; g_clear_object() does this for us, atomically.
+ */
+ // g_clear_object (&self->priv->an_object);
+ g_clear_object (&self->priv->proxy);
+
+
+ /* Always chain up to the parent class; there is no need to check if
+ * the parent class implements the dispose() virtual function: it is
+ * always guaranteed to do so
+ */
+ G_OBJECT_CLASS (manager_parent_class)->dispose (gobject);
+}
+
+static void manager_finalize (GObject *gobject)
+{
+ Manager *self = MANAGER(gobject);
+
+ // g_free(self->priv->a_string);
+
+ /* Always chain up to the parent class; as with dispose(), finalize()
+ * is guaranteed to exist on the parent's class virtual function table
+ */
+ G_OBJECT_CLASS (manager_parent_class)->finalize (gobject);
+}
+
+static void manager_class_init(ManagerClass *klass)
+{
+}
+
+static void manager_init(Manager *self)
+{
+ self->priv = manager_get_instance_private(self);
+ GError *error = NULL;
+
+ g_assert(system_conn != NULL);
+ self->priv->proxy = g_dbus_proxy_new_sync(system_conn, G_DBUS_PROXY_FLAGS_NONE, NULL, BLUEZ_DBUS_SERVICE_NAME, MANAGER_DBUS_PATH, MANAGER_DBUS_INTERFACE, NULL, &error);
+
+ if (self->priv->proxy == NULL)
+ {
+ g_critical("%s", error->message);
+ }
+ g_assert(error == NULL);
+}
+
+Manager *manager_new()
+{
+ return g_object_new(MANAGER_TYPE, NULL);
+}
+
+GVariant *manager_get_managed_objects(Manager *self, GError **error)
+{
+ g_assert(MANAGER_IS(self));
+
+ GVariant *retVal = NULL;
+ retVal = g_dbus_proxy_call_sync(self->priv->proxy, "GetManagedObjects", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+
+ if (retVal != NULL)
+ retVal = g_variant_get_child_value(retVal, 0);
+
+ return retVal;
+}
+
+const gchar *manager_default_adapter(Manager *self, GError **error)
+{
+ g_assert(MANAGER_IS(self));
+
+ GVariant *objects = NULL;
+ objects = manager_get_managed_objects(self, error);
+ if (objects == NULL)
+ return NULL;
+
+ const gchar *object_path;
+ GVariant *ifaces_and_properties;
+ GVariantIter i;
+
+ g_variant_iter_init(&i, objects);
+ while (g_variant_iter_next(&i, "{&o@a{sa{sv}}}", &object_path, &ifaces_and_properties))
+ {
+ const gchar *interface_name;
+ GVariant *properties;
+ GVariantIter ii;
+ g_variant_iter_init(&ii, ifaces_and_properties);
+ while (g_variant_iter_next(&ii, "{&s@a{sv}}", &interface_name, &properties))
+ {
+ if (g_strstr_len(g_ascii_strdown(interface_name, -1), -1, "adapter"))
+ {
+ const gchar *retVal = g_strdup(object_path);
+ g_variant_unref(properties);
+ g_variant_unref(ifaces_and_properties);
+ g_variant_unref(objects);
+ return retVal;
+ }
+ g_variant_unref(properties);
+ }
+ g_variant_unref(ifaces_and_properties);
+ }
+ g_variant_unref(objects);
+
+ return NULL;
+}
+
+const gchar *manager_find_adapter(Manager *self, const gchar *pattern, GError **error)
+{
+ g_assert(MANAGER_IS(self));
+
+ GVariant *objects = NULL;
+ objects = manager_get_managed_objects(self, error);
+ if (objects == NULL)
+ return NULL;
+
+ const gchar *object_path;
+ GVariant *ifaces_and_properties;
+ GVariantIter i;
+
+ g_variant_iter_init(&i, objects);
+ while (g_variant_iter_next(&i, "{&o@a{sa{sv}}}", &object_path, &ifaces_and_properties))
+ {
+ const gchar *interface_name;
+ GVariant *properties;
+ GVariantIter ii;
+ g_variant_iter_init(&ii, ifaces_and_properties);
+ while (g_variant_iter_next(&ii, "{&s@a{sv}}", &interface_name, &properties))
+ {
+ if (g_strstr_len(g_ascii_strdown(interface_name, -1), -1, "adapter"))
+ {
+ const gchar *object_base_name = g_path_get_basename(object_path);
+ if (g_strstr_len(g_ascii_strdown(object_base_name, -1), -1, g_ascii_strdown(pattern, -1)))
+ {
+ const gchar *retVal = g_strdup(object_path);
+ g_variant_unref(properties);
+ g_variant_unref(ifaces_and_properties);
+ g_variant_unref(objects);
+ return retVal;
+ }
+ const gchar *address = g_variant_get_string(g_variant_lookup_value(properties, "Address", NULL), NULL);
+ if (g_strstr_len(g_ascii_strdown(address, -1), -1, g_ascii_strdown(pattern, -1)))
+ {
+ gchar *retVal = g_strdup(object_path);
+ g_variant_unref(properties);
+ g_variant_unref(ifaces_and_properties);
+ g_variant_unref(objects);
+ return retVal;
+ }
+ }
+ g_variant_unref(properties);
+ }
+ g_variant_unref(ifaces_and_properties);
+ }
+ g_variant_unref(objects);
+
+ return NULL;
+}
+
+GPtrArray *manager_get_adapters(Manager *self)
+{
+ g_assert(MANAGER_IS(self));
+
+ GVariant *objects = NULL;
+ GError *error = NULL;
+ objects = manager_get_managed_objects(self, &error);
+ if (objects == NULL)
+ {
+ g_critical("%s", error->message);
+ g_error_free(error);
+ return NULL;
+ }
+
+ GPtrArray *adapter_array = g_ptr_array_new();
+
+ const gchar *object_path;
+ GVariant *ifaces_and_properties;
+ GVariantIter i;
+
+ g_variant_iter_init(&i, objects);
+ while (g_variant_iter_next(&i, "{&o@a{sa{sv}}}", &object_path, &ifaces_and_properties))
+ {
+ const gchar *interface_name;
+ GVariant *properties;
+ GVariantIter ii;
+ g_variant_iter_init(&ii, ifaces_and_properties);
+ while (g_variant_iter_next(&ii, "{&s@a{sv}}", &interface_name, &properties))
+ {
+ if (g_strstr_len(g_ascii_strdown(interface_name, -1), -1, "adapter"))
+ g_ptr_array_add(adapter_array, (gpointer) g_strdup(object_path));
+ g_variant_unref(properties);
+ }
+ g_variant_unref(ifaces_and_properties);
+ }
+ g_variant_unref(objects);
+
+ return adapter_array;
+}
+
+const gchar **manager_get_devices(Manager *self, const gchar *adapter_pattern)
+{
+ g_assert(MANAGER_IS(self));
+
+ GVariant *objects = NULL;
+ GError *error = NULL;
+ objects = manager_get_managed_objects(self, &error);
+ if (objects == NULL)
+ {
+ g_critical("%s", error->message);
+ g_error_free(error);
+ return NULL;
+ }
+
+ GRegex *adapter_regex = g_regex_new(adapter_pattern, 0, 0, &error);
+ if (adapter_regex == NULL)
+ {
+ g_critical("%s", error->message);
+ g_error_free(error);
+ }
+
+ GPtrArray *device_array = g_ptr_array_new();
+
+ const gchar *object_path;
+ GVariant *ifaces_and_properties;
+ GVariantIter i;
+
+ g_variant_iter_init(&i, objects);
+ while (g_variant_iter_next(&i, "{&o@a{sa{sv}}}", &object_path, &ifaces_and_properties))
+ {
+ const gchar *interface_name;
+ GVariant *properties;
+ GVariantIter ii;
+ g_variant_iter_init(&ii, ifaces_and_properties);
+ while (g_variant_iter_next(&ii, "{&s@a{sv}}", &interface_name, &properties))
+ {
+ if (g_strcmp0(interface_name, "org.bluez.Device1") == 0)
+ {
+ const gchar *adapter_prop = g_variant_get_string(g_variant_lookup_value(properties, "Adapter", G_VARIANT_TYPE_OBJECT_PATH), NULL);
+ if(g_regex_match(adapter_regex, adapter_prop, 0, NULL))
+ g_ptr_array_add(device_array, (gpointer) g_strdup(object_path));
+ }
+ g_variant_unref(properties);
+ }
+ g_variant_unref(ifaces_and_properties);
+ }
+ g_variant_unref(objects);
+
+ g_regex_unref(adapter_regex);
+
+ if(device_array->len > 0)
+ {
+ // Top it off with a NULL pointer
+ g_ptr_array_add(device_array, (gpointer) NULL);
+ return (const gchar**) g_ptr_array_free(device_array, FALSE);
+ }
+ else
+ return NULL;
+} \ No newline at end of file