summaryrefslogtreecommitdiff
path: root/src/services/bluetooth-service.c
diff options
context:
space:
mode:
authorHannes Schulze <haschu0103@outlook.de>2025-06-19 23:17:58 +0200
committerHannes Schulze <haschu0103@outlook.de>2025-06-19 23:17:58 +0200
commit1af3d14f3f995645a0de08a54b244c19840709e9 (patch)
tree3c4098863d8a8fd004a2acc8912a23b6036ab4dd /src/services/bluetooth-service.c
parent40efcf60a5f39674b5137f11de7bcfe37fb121b5 (diff)
init hs project
Diffstat (limited to 'src/services/bluetooth-service.c')
-rw-r--r--src/services/bluetooth-service.c949
1 files changed, 0 insertions, 949 deletions
diff --git a/src/services/bluetooth-service.c b/src/services/bluetooth-service.c
deleted file mode 100644
index eb13968..0000000
--- a/src/services/bluetooth-service.c
+++ /dev/null
@@ -1,949 +0,0 @@
-#include "services/bluetooth-service.h"
-#include "dbus/bluez.h"
-#include <gtk/gtk.h>
-
-//
-// FoobarBluetoothDeviceState:
-//
-// The current connection state of a remote bluetooth device.
-//
-
-G_DEFINE_ENUM_TYPE(
- FoobarBluetoothDeviceState,
- foobar_bluetooth_device_state,
- G_DEFINE_ENUM_VALUE( FOOBAR_BLUETOOTH_DEVICE_STATE_DISCONNECTED, "disconnected" ),
- G_DEFINE_ENUM_VALUE( FOOBAR_BLUETOOTH_DEVICE_STATE_CONNECTING, "connecting" ),
- G_DEFINE_ENUM_VALUE( FOOBAR_BLUETOOTH_DEVICE_STATE_CONNECTED, "connected" ) )
-
-//
-// FoobarBluetoothDevice:
-//
-// Represents an external bluetooth device the client can connect to.
-//
-
-struct _FoobarBluetoothDevice
-{
- GObject parent_instance;
- FoobarBluetoothService* service;
- FoobarBluetoothDeviceState state;
- FoobarBluezDevice* device;
- GCancellable* connect_cancellable;
- gulong notify_handler_id;
-};
-
-enum
-{
- DEVICE_PROP_NAME = 1,
- DEVICE_PROP_STATE,
- N_DEVICE_PROPS,
-};
-
-static GParamSpec* device_props[N_DEVICE_PROPS] = { 0 };
-
-static void foobar_bluetooth_device_class_init ( FoobarBluetoothDeviceClass* klass );
-static void foobar_bluetooth_device_init ( FoobarBluetoothDevice* self );
-static void foobar_bluetooth_device_get_property ( GObject* object,
- guint prop_id,
- GValue* value,
- GParamSpec* pspec );
-static void foobar_bluetooth_device_finalize ( GObject* object );
-static FoobarBluetoothDevice* foobar_bluetooth_device_new ( FoobarBluetoothService* service,
- FoobarBluezDevice* device );
-static void foobar_bluetooth_device_handle_notify( GObject* object,
- GParamSpec* pspec,
- gpointer userdata );
-static void foobar_bluetooth_device_connect_cb ( GObject* object,
- GAsyncResult* result,
- gpointer userdata );
-static void foobar_bluetooth_device_disconnect_cb( GObject* object,
- GAsyncResult* result,
- gpointer userdata );
-static void foobar_bluetooth_device_update_state ( FoobarBluetoothDevice* self );
-
-G_DEFINE_FINAL_TYPE( FoobarBluetoothDevice, foobar_bluetooth_device, G_TYPE_OBJECT )
-
-//
-// FoobarBluetoothService:
-//
-// Service managing the state of the bluetooth adapter. This is implemented using the Bluez DBus API.
-//
-
-struct _FoobarBluetoothService
-{
- GObject parent_instance;
- GDBusObjectManager* object_manager;
- GListStore* devices;
- GtkFilterListModel* filtered_devices;
- GtkSortListModel* sorted_devices;
- GtkFilterListModel* connected_devices;
- GPtrArray* adapters; // First adapter is the default one.
- FoobarBluezAdapter* default_adapter;
- gulong interface_added_handler_id;
- gulong interface_removed_handler_id;
- gulong object_added_handler_id;
- gulong object_removed_handler_id;
- gulong adapter_notify_handler_id;
-};
-
-enum
-{
- PROP_DEVICES = 1,
- PROP_CONNECTED_DEVICES,
- PROP_IS_AVAILABLE,
- PROP_IS_ENABLED,
- PROP_IS_SCANNING,
- N_PROPS,
-};
-
-static GParamSpec* props[N_PROPS] = { 0 };
-
-static void foobar_bluetooth_service_class_init ( FoobarBluetoothServiceClass* klass );
-static void foobar_bluetooth_service_init ( FoobarBluetoothService* self );
-static void foobar_bluetooth_service_get_property ( GObject* object,
- guint prop_id,
- GValue* value,
- GParamSpec* pspec );
-static void foobar_bluetooth_service_set_property ( GObject* object,
- guint prop_id,
- GValue const* value,
- GParamSpec* pspec );
-static void foobar_bluetooth_service_finalize ( GObject* object );
-static void foobar_bluetooth_service_handle_interface_added ( GDBusObjectManager* manager,
- GDBusObject* object,
- GDBusInterface* interface,
- gpointer userdata );
-static void foobar_bluetooth_service_handle_interface_removed( GDBusObjectManager* manager,
- GDBusObject* object,
- GDBusInterface* interface,
- gpointer userdata );
-static void foobar_bluetooth_service_handle_object_added ( GDBusObjectManager* manager,
- GDBusObject* object,
- gpointer userdata );
-static void foobar_bluetooth_service_handle_object_removed ( GDBusObjectManager* manager,
- GDBusObject* object,
- gpointer userdata );
-static void foobar_bluetooth_service_handle_adapter_notify ( GObject* object,
- GParamSpec* pspec,
- gpointer userdata );
-static void foobar_bluetooth_service_update_default_adapter ( FoobarBluetoothService* self );
-static GType foobar_bluetooth_service_dbus_proxy_type_cb ( GDBusObjectManagerClient* manager,
- gchar const* object_path,
- gchar const* interface_name,
- gpointer userdata );
-static gboolean foobar_bluetooth_service_filter_func ( gpointer item,
- gpointer userdata );
-static gboolean foobar_bluetooth_service_connected_filter_func ( gpointer item,
- gpointer userdata );
-static gint foobar_bluetooth_service_sort_func ( gconstpointer item_a,
- gconstpointer item_b,
- gpointer userdata );
-
-G_DEFINE_FINAL_TYPE( FoobarBluetoothService, foobar_bluetooth_service, G_TYPE_OBJECT )
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Device
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Static initialization for devices.
-//
-void foobar_bluetooth_device_class_init( FoobarBluetoothDeviceClass* klass )
-{
- GObjectClass* object_klass = G_OBJECT_CLASS( klass );
- object_klass->get_property = foobar_bluetooth_device_get_property;
- object_klass->finalize = foobar_bluetooth_device_finalize;
-
- device_props[DEVICE_PROP_NAME] = g_param_spec_string(
- "name",
- "Name",
- "Human-readable name for the device.",
- NULL,
- G_PARAM_READABLE );
- device_props[DEVICE_PROP_STATE] = g_param_spec_enum(
- "state",
- "State",
- "Current connection state of the device.",
- FOOBAR_TYPE_BLUETOOTH_DEVICE_STATE,
- 0,
- G_PARAM_READABLE );
- g_object_class_install_properties( object_klass, N_DEVICE_PROPS, device_props );
-}
-
-//
-// Instance initialization for devices.
-//
-void foobar_bluetooth_device_init( FoobarBluetoothDevice* self )
-{
- (void)self;
-}
-
-//
-// Property getter implementation, mapping a property id to a method.
-//
-void foobar_bluetooth_device_get_property(
- GObject* object,
- guint prop_id,
- GValue* value,
- GParamSpec* pspec )
-{
- FoobarBluetoothDevice* self = (FoobarBluetoothDevice*)object;
-
- switch ( prop_id )
- {
- case DEVICE_PROP_NAME:
- g_value_set_string( value, foobar_bluetooth_device_get_name( self ) );
- break;
- case DEVICE_PROP_STATE:
- g_value_set_enum( value, foobar_bluetooth_device_get_state( self ) );
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
- break;
- }
-}
-
-//
-// Instance cleanup for devices.
-//
-void foobar_bluetooth_device_finalize( GObject* object )
-{
- FoobarBluetoothDevice* self = (FoobarBluetoothDevice*)object;
-
- g_clear_signal_handler( &self->notify_handler_id, self->device );
- g_clear_object( &self->device );
- g_clear_object( &self->connect_cancellable );
-
- G_OBJECT_CLASS( foobar_bluetooth_device_parent_class )->finalize( object );
-}
-
-//
-// Create a new device object, wrapping a DBus device instance.
-//
-FoobarBluetoothDevice* foobar_bluetooth_device_new(
- FoobarBluetoothService* service,
- FoobarBluezDevice* device )
-{
- FoobarBluetoothDevice* self = g_object_new( FOOBAR_TYPE_BLUETOOTH_DEVICE, NULL );
-
- self->service = service;
- self->device = g_object_ref( device );
- foobar_bluetooth_device_update_state( self );
-
- self->notify_handler_id = g_signal_connect(
- self->device, "notify", G_CALLBACK( foobar_bluetooth_device_handle_notify ), self );
-
- return self;
-}
-
-//
-// Get the name/alias for the device.
-//
-gchar const* foobar_bluetooth_device_get_name( FoobarBluetoothDevice* self )
-{
- g_return_val_if_fail( FOOBAR_IS_BLUETOOTH_DEVICE( self ), NULL );
- return foobar_bluez_device_get_alias( self->device );
-}
-
-//
-// Get the current connection state for the device.
-//
-FoobarBluetoothDeviceState foobar_bluetooth_device_get_state( FoobarBluetoothDevice* self )
-{
- g_return_val_if_fail( FOOBAR_IS_BLUETOOTH_DEVICE( self ), 0 );
- return self->state;
-}
-
-//
-// Toggle whether the device is connected:
-//
-// - If the device is currently disconnected, it is connected.
-// - If the device is currently being connected, that process is aborted.
-// - If the device is currently connected, it is disconnected.
-//
-void foobar_bluetooth_device_toggle_connection( FoobarBluetoothDevice* self )
-{
- g_return_if_fail( FOOBAR_IS_BLUETOOTH_DEVICE( self ) );
-
- switch ( self->state )
- {
- case FOOBAR_BLUETOOTH_DEVICE_STATE_DISCONNECTED:
- self->connect_cancellable = g_cancellable_new( );
- foobar_bluetooth_device_update_state( self );
- foobar_bluez_device_call_connect(
- self->device,
- self->connect_cancellable,
- foobar_bluetooth_device_connect_cb,
- g_object_ref( self ) );
- break;
- case FOOBAR_BLUETOOTH_DEVICE_STATE_CONNECTING:
- g_cancellable_cancel( self->connect_cancellable );
- break;
- case FOOBAR_BLUETOOTH_DEVICE_STATE_CONNECTED:
- foobar_bluez_device_call_disconnect(
- self->device,
- NULL,
- foobar_bluetooth_device_disconnect_cb,
- g_object_ref( self ) );
- break;
- default:
- g_warn_if_reached( );
- }
-}
-
-//
-// Called by the underlying device when one of its properties changes.
-//
-void foobar_bluetooth_device_handle_notify(
- GObject* object,
- GParamSpec* pspec,
- gpointer userdata )
-{
- (void)object;
- FoobarBluetoothDevice* self = (FoobarBluetoothDevice*)userdata;
-
- gchar const* property = g_param_spec_get_name( pspec );
- if ( !g_strcmp0( property, "alias" ) )
- {
- g_object_notify_by_pspec( G_OBJECT( self ), device_props[DEVICE_PROP_NAME] );
- }
- else if ( !g_strcmp0( property, "name" ) || !g_strcmp0( property, "adapter" ) )
- {
- if ( self->service )
- {
- gtk_filter_changed(
- gtk_filter_list_model_get_filter( self->service->filtered_devices ),
- GTK_FILTER_CHANGE_DIFFERENT );
- }
- }
- else if ( !g_strcmp0( property, "connected" ) )
- {
- foobar_bluetooth_device_update_state( self );
- }
-}
-
-//
-// Called when a request to connect the device is completed.
-//
-// This is mainly used to update the device's state.
-//
-void foobar_bluetooth_device_connect_cb(
- GObject* object,
- GAsyncResult* result,
- gpointer userdata )
-{
- (void)object;
- g_autoptr( FoobarBluetoothDevice ) self = (FoobarBluetoothDevice*)userdata;
-
- g_autoptr( GError ) error = NULL;
- if ( !foobar_bluez_device_call_connect_finish( self->device, result, &error ) )
- {
- g_warning( "Unable to connect bluetooth device: %s", error->message );
- }
-
- g_clear_object( &self->connect_cancellable );
- foobar_bluetooth_device_update_state( self );
-}
-
-//
-// Called when a request to disconnect the device is completed.
-//
-void foobar_bluetooth_device_disconnect_cb(
- GObject* object,
- GAsyncResult* result,
- gpointer userdata )
-{
- (void)object;
- g_autoptr( FoobarBluetoothDevice ) self = (FoobarBluetoothDevice*)userdata;
-
- g_autoptr( GError ) error = NULL;
- if ( !foobar_bluez_device_call_disconnect_finish( self->device, result, &error ) )
- {
- g_warning( "Unable to disconnect bluetooth device: %s", error->message );
- }
-}
-
-//
-// Update the current device state.
-//
-// The connect_cancellable member variable is used to indicate an ongoing connection attempt. Otherwise, the value of
-// is_connected is used.
-//
-void foobar_bluetooth_device_update_state( FoobarBluetoothDevice* self )
-{
- FoobarBluetoothDeviceState new_state = foobar_bluez_device_get_connected( self->device )
- ? FOOBAR_BLUETOOTH_DEVICE_STATE_CONNECTED
- : FOOBAR_BLUETOOTH_DEVICE_STATE_DISCONNECTED;
- if ( self->connect_cancellable )
- {
- new_state = FOOBAR_BLUETOOTH_DEVICE_STATE_CONNECTING;
- }
-
- if ( self->state != new_state )
- {
- self->state = new_state;
- g_object_notify_by_pspec( G_OBJECT( self ), device_props[DEVICE_PROP_STATE] );
-
- if ( self->service )
- {
- gtk_filter_changed(
- gtk_filter_list_model_get_filter( self->service->connected_devices ),
- GTK_FILTER_CHANGE_DIFFERENT );
- }
- }
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Service Implementation
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Static initialization for the bluetooth service.
-//
-void foobar_bluetooth_service_class_init( FoobarBluetoothServiceClass* klass )
-{
- GObjectClass* object_klass = G_OBJECT_CLASS( klass );
- object_klass->get_property = foobar_bluetooth_service_get_property;
- object_klass->set_property = foobar_bluetooth_service_set_property;
- object_klass->finalize = foobar_bluetooth_service_finalize;
-
- props[PROP_DEVICES] = g_param_spec_object(
- "devices",
- "Devices",
- "Sorted list of available bluetooth devices.",
- G_TYPE_LIST_MODEL,
- G_PARAM_READABLE );
- props[PROP_CONNECTED_DEVICES] = g_param_spec_object(
- "connected-devices",
- "Connected Devices",
- "Sorted list of currently connected bluetooth devices.",
- G_TYPE_LIST_MODEL,
- G_PARAM_READABLE );
- props[PROP_IS_AVAILABLE] = g_param_spec_boolean(
- "is-available",
- "Is Available",
- "Indicates whether the system has a bluetooth adapter.",
- FALSE,
- G_PARAM_READABLE );
- props[PROP_IS_ENABLED] = g_param_spec_boolean(
- "is-enabled",
- "Is Enabled",
- "Indicates whether the bluetooth adapter is currently enabled.",
- FALSE,
- G_PARAM_READWRITE );
- props[PROP_IS_SCANNING] = g_param_spec_boolean(
- "is-scanning",
- "Is Scanning",
- "Indicates whether the bluetooth adapter is currently scanning for devices.",
- FALSE,
- G_PARAM_READWRITE );
- g_object_class_install_properties( object_klass, N_PROPS, props );
-}
-
-//
-// Instance initialization for the bluetooth service.
-//
-void foobar_bluetooth_service_init( FoobarBluetoothService* self )
-{
- self->devices = g_list_store_new( FOOBAR_TYPE_BLUETOOTH_DEVICE );
-
- GtkCustomFilter* filter = gtk_custom_filter_new( foobar_bluetooth_service_filter_func, self, NULL );
- self->filtered_devices = gtk_filter_list_model_new(
- G_LIST_MODEL( g_object_ref( self->devices ) ),
- GTK_FILTER( filter ) );
-
- GtkCustomSorter* sorter = gtk_custom_sorter_new( foobar_bluetooth_service_sort_func, NULL, NULL );
- self->sorted_devices = gtk_sort_list_model_new(
- G_LIST_MODEL( g_object_ref( self->filtered_devices ) ),
- GTK_SORTER( sorter ) );
-
- GtkCustomFilter* connected_filter = gtk_custom_filter_new( foobar_bluetooth_service_connected_filter_func, NULL, NULL );
- self->connected_devices = gtk_filter_list_model_new(
- G_LIST_MODEL( g_object_ref( self->sorted_devices ) ),
- GTK_FILTER( connected_filter ) );
-
- self->adapters = g_ptr_array_new_with_free_func( g_object_unref );
-
- g_autoptr( GError ) error = NULL;
- self->object_manager = g_dbus_object_manager_client_new_for_bus_sync(
- G_BUS_TYPE_SYSTEM,
- G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START,
- "org.bluez",
- "/",
- foobar_bluetooth_service_dbus_proxy_type_cb,
- NULL,
- NULL,
- NULL,
- &error );
-
- if ( self->object_manager )
- {
- self->interface_added_handler_id = g_signal_connect(
- self->object_manager,
- "interface-added",
- G_CALLBACK( foobar_bluetooth_service_handle_interface_added ),
- self );
- self->interface_removed_handler_id = g_signal_connect(
- self->object_manager,
- "interface-removed",
- G_CALLBACK( foobar_bluetooth_service_handle_interface_removed ),
- self );
- self->object_added_handler_id = g_signal_connect(
- self->object_manager,
- "object-added",
- G_CALLBACK( foobar_bluetooth_service_handle_object_added ),
- self );
- self->object_removed_handler_id = g_signal_connect(
- self->object_manager,
- "object-removed",
- G_CALLBACK( foobar_bluetooth_service_handle_object_removed ),
- self );
-
- g_autolist( GDBusObject ) objects = g_dbus_object_manager_get_objects( self->object_manager );
- for ( GList* it = objects; it; it = it->next )
- {
- foobar_bluetooth_service_handle_object_added( self->object_manager, it->data, self );
- }
- }
- else
- {
- g_warning( "Unable to create a DBus object manager for communication with Bluez: %s", error->message );
- }
-}
-
-//
-// Property getter implementation, mapping a property id to a method.
-//
-void foobar_bluetooth_service_get_property(
- GObject* object,
- guint prop_id,
- GValue* value,
- GParamSpec* pspec )
-{
- FoobarBluetoothService* self = (FoobarBluetoothService*)object;
-
- switch ( prop_id )
- {
- case PROP_DEVICES:
- g_value_set_object( value, foobar_bluetooth_service_get_devices( self ) );
- break;
- case PROP_CONNECTED_DEVICES:
- g_value_set_object( value, foobar_bluetooth_service_get_connected_devices( self ) );
- break;
- case PROP_IS_AVAILABLE:
- g_value_set_boolean( value, foobar_bluetooth_service_is_available( self ) );
- break;
- case PROP_IS_ENABLED:
- g_value_set_boolean( value, foobar_bluetooth_service_is_enabled( self ) );
- break;
- case PROP_IS_SCANNING:
- g_value_set_boolean( value, foobar_bluetooth_service_is_scanning( self ) );
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
- break;
- }
-}
-
-//
-// Property setter implementation, mapping a property id to a method.
-//
-void foobar_bluetooth_service_set_property(
- GObject* object,
- guint prop_id,
- GValue const* value,
- GParamSpec* pspec )
-{
- FoobarBluetoothService* self = (FoobarBluetoothService*)object;
-
- switch ( prop_id )
- {
- case PROP_IS_ENABLED:
- foobar_bluetooth_service_set_enabled( self, g_value_get_boolean( value ) );
- break;
- case PROP_IS_SCANNING:
- foobar_bluetooth_service_set_scanning( self, g_value_get_boolean( value ) );
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
- break;
- }
-}
-
-//
-// Instance cleanup for the bluetooth service.
-//
-void foobar_bluetooth_service_finalize( GObject* object )
-{
- FoobarBluetoothService* self = (FoobarBluetoothService*)object;
-
- for ( guint i = 0; i < g_list_model_get_n_items( G_LIST_MODEL( self->devices ) ); ++i )
- {
- FoobarBluetoothDevice* device = g_list_model_get_item( G_LIST_MODEL( self->devices ), i );
- device->service = NULL;
- }
-
- g_clear_signal_handler( &self->adapter_notify_handler_id, self->default_adapter );
- g_clear_signal_handler( &self->interface_added_handler_id, self->object_manager );
- g_clear_signal_handler( &self->interface_removed_handler_id, self->object_manager );
- g_clear_signal_handler( &self->object_added_handler_id, self->object_manager );
- g_clear_signal_handler( &self->object_removed_handler_id, self->object_manager );
- g_clear_object( &self->object_manager );
- g_clear_object( &self->connected_devices );
- g_clear_object( &self->sorted_devices );
- g_clear_object( &self->filtered_devices );
- g_clear_object( &self->devices );
- g_clear_object( &self->default_adapter );
- g_clear_pointer( &self->adapters, g_ptr_array_unref );
-
- G_OBJECT_CLASS( foobar_bluetooth_service_parent_class )->finalize( object );
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Public API
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Create a new bluetooth service instance.
-//
-FoobarBluetoothService* foobar_bluetooth_service_new( void )
-{
- return g_object_new( FOOBAR_TYPE_BLUETOOTH_SERVICE, NULL );
-}
-
-//
-// Get the sorted list of available bluetooth devices.
-//
-GListModel* foobar_bluetooth_service_get_devices( FoobarBluetoothService* self )
-{
- g_return_val_if_fail( FOOBAR_IS_BLUETOOTH_SERVICE( self ), NULL );
- return G_LIST_MODEL( self->sorted_devices );
-}
-
-//
-// Get the sorted list of currently connected bluetooth devices.
-//
-GListModel* foobar_bluetooth_service_get_connected_devices( FoobarBluetoothService* self )
-{
- g_return_val_if_fail( FOOBAR_IS_BLUETOOTH_SERVICE( self ), NULL );
- return G_LIST_MODEL( self->connected_devices );
-}
-
-//
-// Check whether the system has a bluetooth adapter.
-//
-gboolean foobar_bluetooth_service_is_available( FoobarBluetoothService* self )
-{
- g_return_val_if_fail( FOOBAR_IS_BLUETOOTH_SERVICE( self ), FALSE );
- return self->default_adapter != NULL;
-}
-
-//
-// Check whether the bluetooth adapter is currently enabled.
-//
-gboolean foobar_bluetooth_service_is_enabled( FoobarBluetoothService* self )
-{
- g_return_val_if_fail( FOOBAR_IS_BLUETOOTH_SERVICE( self ), FALSE );
- return self->default_adapter ? foobar_bluez_adapter_get_powered( self->default_adapter ) : FALSE;
-}
-
-//
-// Check whether the bluetooth adapter is currently scanning for devices.
-//
-gboolean foobar_bluetooth_service_is_scanning( FoobarBluetoothService* self )
-{
- g_return_val_if_fail( FOOBAR_IS_BLUETOOTH_SERVICE( self ), FALSE );
- return self->default_adapter ? foobar_bluez_adapter_get_discovering( self->default_adapter ) : FALSE;
-}
-
-//
-// Update whether the bluetooth adapter is currently enabled.
-//
-void foobar_bluetooth_service_set_enabled(
- FoobarBluetoothService* self,
- gboolean value )
-{
- g_return_if_fail( FOOBAR_IS_BLUETOOTH_SERVICE( self ) );
-
- if (self->default_adapter)
- {
- foobar_bluez_adapter_set_powered( self->default_adapter, value );
- }
-}
-
-//
-// Update whether the bluetooth adapter is currently scanning for devices.
-//
-void foobar_bluetooth_service_set_scanning(
- FoobarBluetoothService* self,
- gboolean value )
-{
- g_return_if_fail( FOOBAR_IS_BLUETOOTH_SERVICE( self ) );
-
- g_autoptr( GError ) error = NULL;
-
- if (self->default_adapter && foobar_bluetooth_service_is_scanning( self ) != value)
- {
- if (value)
- {
- // Make this device discoverable while discovery is active.
-
- GVariantBuilder filter_builder;
- g_variant_builder_init( &filter_builder, G_VARIANT_TYPE_VARDICT );
- g_variant_builder_add( &filter_builder, "{sv}", "Discoverable", g_variant_new_boolean( TRUE ) );
- GVariant* filter = g_variant_builder_end( &filter_builder );
- if ( !foobar_bluez_adapter_call_set_discovery_filter_sync( self->default_adapter, filter, NULL, &error ) )
- {
- g_warning( "Failed to set discovery filter: %s", error->message );
- return;
- }
- if ( !foobar_bluez_adapter_call_start_discovery_sync( self->default_adapter, NULL, &error ) )
- {
- g_warning( "Failed to start discovery: %s", error->message );
- }
- }
- else
- {
- if ( !foobar_bluez_adapter_call_stop_discovery_sync( self->default_adapter, NULL, &error ) )
- {
- g_warning( "Failed to stop discovery: %s", error->message );
- }
- }
- }
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Signal Handlers
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Called when an interface was added to an existing DBus object (either adapter or device).
-//
-void foobar_bluetooth_service_handle_interface_added(
- GDBusObjectManager* manager,
- GDBusObject* object,
- GDBusInterface* interface,
- gpointer userdata )
-{
- (void)manager;
- (void)object;
- FoobarBluetoothService* self = (FoobarBluetoothService*)userdata;
-
- if ( FOOBAR_IS_BLUEZ_DEVICE( interface ) )
- {
- g_autoptr( FoobarBluetoothDevice ) device = foobar_bluetooth_device_new(
- self,
- FOOBAR_BLUEZ_DEVICE( interface ) );
- g_list_store_append( self->devices, device );
- }
- else if ( FOOBAR_IS_BLUEZ_ADAPTER( interface ) )
- {
- g_ptr_array_add( self->adapters, g_object_ref( interface ) );
- foobar_bluetooth_service_update_default_adapter( self );
- }
-}
-
-//
-// Called when an interface was removed from an existing DBus object (either adapter or device).
-//
-void foobar_bluetooth_service_handle_interface_removed(
- GDBusObjectManager* manager,
- GDBusObject* object,
- GDBusInterface* interface,
- gpointer userdata )
-{
- (void)manager;
- FoobarBluetoothService* self = (FoobarBluetoothService*)userdata;
-
- gchar const* removed_path = g_dbus_object_get_object_path( object );
- if ( FOOBAR_IS_BLUEZ_DEVICE( interface ) )
- {
- for ( guint i = 0; i < g_list_model_get_n_items( G_LIST_MODEL( self->devices ) ); ++i )
- {
- FoobarBluetoothDevice* device = g_list_model_get_item( G_LIST_MODEL( self->devices ), i );
- gchar const* path = g_dbus_proxy_get_object_path( G_DBUS_PROXY( device->device ) );
- if ( !g_strcmp0( path, removed_path ) )
- {
- device->service = NULL;
- g_list_store_remove( self->devices, i );
- break;
- }
- }
- }
- else if ( FOOBAR_IS_BLUEZ_ADAPTER( interface ) )
- {
- for ( guint i = 0; i < self->adapters->len; ++i )
- {
- FoobarBluezAdapter* adapter = g_ptr_array_index( self->adapters, i );
- gchar const* path = g_dbus_proxy_get_object_path( G_DBUS_PROXY( adapter ) );
- if ( !g_strcmp0( path, removed_path ) )
- {
- g_ptr_array_remove_index( self->adapters, i );
- break;
- }
- }
- foobar_bluetooth_service_update_default_adapter( self );
- }
-}
-
-//
-// Called when a DBus object was added (either adapter or device).
-//
-void foobar_bluetooth_service_handle_object_added(
- GDBusObjectManager* manager,
- GDBusObject* object,
- gpointer userdata )
-{
- g_autolist( GDBusInterface ) interfaces = g_dbus_object_get_interfaces( object );
- for ( GList* it = interfaces; it; it = it->next )
- {
- foobar_bluetooth_service_handle_interface_added( manager, object, it->data, userdata );
- }
-}
-
-//
-// Called when a DBus object was removed (either adapter or device).
-//
-void foobar_bluetooth_service_handle_object_removed(
- GDBusObjectManager* manager,
- GDBusObject* object,
- gpointer userdata )
-{
- g_autolist( GDBusInterface ) interfaces = g_dbus_object_get_interfaces( object );
- for ( GList* it = interfaces; it; it = it->next )
- {
- foobar_bluetooth_service_handle_interface_removed( manager, object, it->data, userdata );
- }
-}
-
-//
-// Called when a property of the default adapter has changed.
-//
-void foobar_bluetooth_service_handle_adapter_notify(
- GObject* object,
- GParamSpec* pspec,
- gpointer userdata )
-{
- (void)object;
- FoobarBluetoothService* self = (FoobarBluetoothService*)userdata;
-
- gchar const* property = g_param_spec_get_name( pspec );
- if ( !g_strcmp0( property, "powered" ) )
- {
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_IS_ENABLED] );
- }
- else if ( !g_strcmp0( property, "discovering" ) )
- {
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_IS_SCANNING] );
- }
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Helper Methods
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Update the default_adapter to match the first item in the adapters array.
-//
-void foobar_bluetooth_service_update_default_adapter( FoobarBluetoothService* self )
-{
- FoobarBluezAdapter* new_adapter = ( self->adapters->len > 0 ) ? g_ptr_array_index( self->adapters, 0 ) : NULL;
-
- if ( self->default_adapter != new_adapter )
- {
- g_clear_signal_handler( &self->adapter_notify_handler_id, self->default_adapter );
- g_clear_object( &self->default_adapter );
-
- if ( new_adapter )
- {
- self->default_adapter = g_object_ref( new_adapter );
- self->adapter_notify_handler_id = g_signal_connect(
- self->default_adapter,
- "notify",
- G_CALLBACK( foobar_bluetooth_service_handle_adapter_notify ),
- self );
- }
-
- gtk_filter_changed( gtk_filter_list_model_get_filter( self->filtered_devices ), GTK_FILTER_CHANGE_DIFFERENT );
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_IS_AVAILABLE] );
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_IS_ENABLED] );
- g_object_notify_by_pspec( G_OBJECT( self ), props[PROP_IS_SCANNING] );
- }
-}
-
-//
-// Get the type for creating a DBus proxy object.
-//
-// This is used because the DBus object manager should give us instances of the FoobarBluezAdapterProxy and
-// FoobarBluezDeviceProxy types.
-//
-GType foobar_bluetooth_service_dbus_proxy_type_cb(
- GDBusObjectManagerClient* manager,
- gchar const* object_path,
- gchar const* interface_name,
- gpointer userdata )
-{
- if ( !interface_name )
- {
- return G_TYPE_DBUS_OBJECT_PROXY;
- }
-
- if ( !g_strcmp0( interface_name, "org.bluez.Device1" ) )
- {
- return FOOBAR_TYPE_BLUEZ_DEVICE_PROXY;
- }
-
- if ( !g_strcmp0( interface_name, "org.bluez.Adapter1" ) )
- {
- return FOOBAR_TYPE_BLUEZ_ADAPTER_PROXY;
- }
-
- return G_TYPE_DBUS_PROXY;
-}
-
-//
-// Filtering callback for the list of devices, only showing devices from the default adapter.
-//
-gboolean foobar_bluetooth_service_filter_func(
- gpointer item,
- gpointer userdata )
-{
- FoobarBluetoothService* self = (FoobarBluetoothService*)userdata;
- FoobarBluetoothDevice* device = item;
-
- gchar const* device_adapter = foobar_bluez_device_get_adapter( device->device );
- gchar const* default_adapter = self->default_adapter
- ? g_dbus_proxy_get_object_path( G_DBUS_PROXY( self->default_adapter ) )
- : NULL;
- gchar const* name = foobar_bluez_device_get_name( device->device );
- return name != NULL && !g_strcmp0( device_adapter, default_adapter );
-}
-
-//
-// Filtering callback for the list of connected devices.
-//
-gboolean foobar_bluetooth_service_connected_filter_func(
- gpointer item,
- gpointer userdata )
-{
- (void)userdata;
-
- FoobarBluetoothDevice* device = item;
- return foobar_bluetooth_device_get_state( device ) == FOOBAR_BLUETOOTH_DEVICE_STATE_CONNECTED;
-}
-
-//
-// Sorting callback for the list of devices.
-//
-// Devices are sorted by their names.
-//
-gint foobar_bluetooth_service_sort_func(
- gconstpointer item_a,
- gconstpointer item_b,
- gpointer userdata )
-{
- (void)userdata;
-
- FoobarBluetoothDevice* device_a = (FoobarBluetoothDevice*)item_a;
- FoobarBluetoothDevice* device_b = (FoobarBluetoothDevice*)item_b;
- return g_strcmp0( foobar_bluetooth_device_get_name( device_a ), foobar_bluetooth_device_get_name( device_b ) );
-}