main: Make Claim* calls work before sensor is available
It's tedious for clients to know whether they can call Release* when sensors disappear, or making sure that the device is claimed before releasing it when they go in power save mode. You can now claim the sensor whether it's available or not, and it will automatically start sending out the updates when it appears. Closes #23
This commit is contained in:
@@ -132,6 +132,23 @@ find_sensors (GUdevClient *client,
|
||||
return found;
|
||||
}
|
||||
|
||||
static void
|
||||
free_client_watch (gpointer data)
|
||||
{
|
||||
guint watch_id = GPOINTER_TO_UINT (data);
|
||||
|
||||
if (watch_id == 0)
|
||||
return;
|
||||
g_bus_unwatch_name (watch_id);
|
||||
}
|
||||
|
||||
static GHashTable *
|
||||
create_clients_hash_table (void)
|
||||
{
|
||||
return g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, free_client_watch);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
PROP_HAS_ACCELEROMETER = 1 << 0,
|
||||
PROP_ACCELEROMETER_ORIENTATION = 1 << 1,
|
||||
@@ -233,11 +250,10 @@ any_sensors_left (SensorData *data)
|
||||
return exists;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static void
|
||||
client_release (SensorData *data,
|
||||
const char *sender,
|
||||
DriverType driver_type,
|
||||
GDBusMethodInvocation *invocation)
|
||||
DriverType driver_type)
|
||||
{
|
||||
GHashTable *ht;
|
||||
guint watch_id;
|
||||
@@ -245,24 +261,13 @@ client_release (SensorData *data,
|
||||
ht = data->clients[driver_type];
|
||||
|
||||
watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender));
|
||||
if (watch_id == 0) {
|
||||
if (invocation) {
|
||||
g_dbus_method_invocation_return_error (invocation,
|
||||
G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_FAILED,
|
||||
"D-Bus client '%s' is not monitoring %s",
|
||||
sender, driver_type_to_str (driver_type));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if (watch_id == 0)
|
||||
return;
|
||||
|
||||
g_bus_unwatch_name (watch_id);
|
||||
g_hash_table_remove (ht, sender);
|
||||
|
||||
if (g_hash_table_size (ht) == 0)
|
||||
driver_set_polling (DRIVER_FOR_TYPE(driver_type), FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -288,7 +293,7 @@ client_vanished_cb (GDBusConnection *connection,
|
||||
|
||||
watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender));
|
||||
if (watch_id > 0)
|
||||
client_release (data, sender, i, NULL);
|
||||
client_release (data, sender, i);
|
||||
}
|
||||
|
||||
g_free (sender);
|
||||
@@ -323,15 +328,6 @@ handle_method_call (GDBusConnection *connection,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if we have a sensor for that type */
|
||||
if (!driver_type_exists (data, driver_type)) {
|
||||
g_dbus_method_invocation_return_error (invocation,
|
||||
G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_INVALID_ARGS,
|
||||
"Driver type '%s' is not present", driver_type_to_str (driver_type));
|
||||
return;
|
||||
}
|
||||
|
||||
ht = data->clients[driver_type];
|
||||
|
||||
if (g_str_has_prefix (method_name, "Claim")) {
|
||||
@@ -346,7 +342,8 @@ handle_method_call (GDBusConnection *connection,
|
||||
}
|
||||
|
||||
/* No other clients for this sensor? Start it */
|
||||
if (g_hash_table_size (ht) == 0)
|
||||
if (driver_type_exists (data, driver_type) &&
|
||||
g_hash_table_size (ht) == 0)
|
||||
driver_set_polling (DRIVER_FOR_TYPE(driver_type), TRUE);
|
||||
|
||||
watch_id = g_bus_watch_name_on_connection (data->connection,
|
||||
@@ -360,7 +357,7 @@ handle_method_call (GDBusConnection *connection,
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
} else if (g_str_has_prefix (method_name, "Release")) {
|
||||
if (client_release (data, sender, driver_type, invocation))
|
||||
client_release (data, sender, driver_type);
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
}
|
||||
}
|
||||
@@ -576,8 +573,13 @@ sensor_changes (GUdevClient *client,
|
||||
g_debug ("Sensor type %s got removed (%s)",
|
||||
driver_type_to_str (i),
|
||||
g_udev_device_get_sysfs_path (dev));
|
||||
|
||||
g_clear_object (&DEVICE_FOR_TYPE(i));
|
||||
DRIVER_FOR_TYPE(i) = NULL;
|
||||
|
||||
g_clear_pointer (&data->clients[i], g_hash_table_unref);
|
||||
data->clients[i] = create_clients_hash_table ();
|
||||
|
||||
send_driver_changed_dbus_event (data, i);
|
||||
}
|
||||
}
|
||||
@@ -598,9 +600,16 @@ sensor_changes (GUdevClient *client,
|
||||
|
||||
if (driver_open (driver, device,
|
||||
driver_type_to_callback_func (driver->type), data)) {
|
||||
GHashTable *ht;
|
||||
|
||||
DEVICE_FOR_TYPE(driver->type) = g_object_ref (device);
|
||||
DRIVER_FOR_TYPE(driver->type) = (SensorDriver *) driver;
|
||||
send_driver_changed_dbus_event (data, driver->type);
|
||||
|
||||
ht = data->clients[driver->type];
|
||||
|
||||
if (g_hash_table_size (ht) > 0)
|
||||
driver_set_polling (DRIVER_FOR_TYPE(driver->type), TRUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -634,10 +643,7 @@ int main (int argc, char **argv)
|
||||
G_CALLBACK (sensor_changes), data);
|
||||
|
||||
for (i = 0; i < NUM_SENSOR_TYPES; i++) {
|
||||
data->clients[i] = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
NULL);
|
||||
data->clients[i] = create_clients_hash_table ();
|
||||
|
||||
if (!driver_type_exists (data, i))
|
||||
continue;
|
||||
|
@@ -58,10 +58,6 @@ appeared_cb (GDBusConnection *connection,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gboolean has_accel, has_als;
|
||||
GVariant *v;
|
||||
|
||||
has_accel = has_als = FALSE;
|
||||
|
||||
iio_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
@@ -75,12 +71,6 @@ appeared_cb (GDBusConnection *connection,
|
||||
G_CALLBACK (properties_changed), NULL);
|
||||
|
||||
/* Accelerometer */
|
||||
v = g_dbus_proxy_get_cached_property (iio_proxy, "HasAccelerometer");
|
||||
if (v) {
|
||||
has_accel = g_variant_get_boolean (v);
|
||||
g_variant_unref (v);
|
||||
}
|
||||
if (has_accel && !accel_claimed) {
|
||||
g_dbus_proxy_call_sync (iio_proxy,
|
||||
"ClaimAccelerometer",
|
||||
NULL,
|
||||
@@ -88,16 +78,8 @@ appeared_cb (GDBusConnection *connection,
|
||||
-1,
|
||||
NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
accel_claimed = TRUE;
|
||||
}
|
||||
|
||||
/* ALS */
|
||||
v = g_dbus_proxy_get_cached_property (iio_proxy, "HasAmbientLight");
|
||||
if (v) {
|
||||
has_als = g_variant_get_boolean (v);
|
||||
g_variant_unref (v);
|
||||
}
|
||||
if (has_als && !als_claimed) {
|
||||
g_dbus_proxy_call_sync (iio_proxy,
|
||||
"ClaimLight",
|
||||
NULL,
|
||||
@@ -105,8 +87,6 @@ appeared_cb (GDBusConnection *connection,
|
||||
-1,
|
||||
NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
als_claimed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -66,7 +66,9 @@
|
||||
ClaimAccelerometer:
|
||||
|
||||
To start receiving accelerometer reading updates from the proxy, the application
|
||||
must call the net.hadess.SensorProxy.ClaimAccelerometer() method.
|
||||
must call the net.hadess.SensorProxy.ClaimAccelerometer() method. It can do so
|
||||
whether an accelerometer is available or not, updates would then be sent when an
|
||||
accelerometer appears.
|
||||
|
||||
Applications should call net.hadess.SensorProxy.ReleaseAccelerometer() when
|
||||
readings are not required anymore. For example, an application that monitors
|
||||
@@ -83,7 +85,7 @@
|
||||
|
||||
This should be called as soon as readings are not required anymore. Note
|
||||
that resources are freed up if a monitoring application exits without
|
||||
calling net.hadess.SensorProxy.Release(), or crashes.
|
||||
calling net.hadess.SensorProxy.Release(), crashes or the sensor disappears.
|
||||
-->
|
||||
<method name="ReleaseAccelerometer"/>
|
||||
|
||||
@@ -91,7 +93,9 @@
|
||||
ClaimLight:
|
||||
|
||||
To start receiving ambient light sensor reading updates from the proxy, the
|
||||
application must call the net.hadess.SensorProxy.ClaimLight() method.
|
||||
application must call the net.hadess.SensorProxy.ClaimLight() method. It can do so
|
||||
whether an ambient light sensor is available or not, updates would then be sent
|
||||
when such a sensor appears.
|
||||
|
||||
Applications should call net.hadess.SensorProxy.ReleaseLight() when readings are
|
||||
not required anymore. For example, an application that monitors the ambient light
|
||||
@@ -108,7 +112,7 @@
|
||||
|
||||
This should be called as soon as readings are not required anymore. Note
|
||||
that resources are freed up if a monitoring application exits without
|
||||
calling net.hadess.SensorProxy.Release(), or crashes.
|
||||
calling net.hadess.SensorProxy.Release(), crashes or the sensor disappears.
|
||||
-->
|
||||
<method name="ReleaseLight"/>
|
||||
|
||||
|
Reference in New Issue
Block a user