g_dbus_proxy_get_interface_name
g_dbus_proxy_get_default_timeout
g_dbus_proxy_set_default_timeout
-g_dbus_proxy_get_cached_property_names
g_dbus_proxy_get_cached_property
+g_dbus_proxy_set_cached_property
+g_dbus_proxy_get_cached_property_names
g_dbus_proxy_set_interface_info
g_dbus_proxy_get_interface_info
g_dbus_proxy_call
return names;
}
+static const GDBusPropertyInfo *
+lookup_property_info_or_warn (GDBusProxy *proxy,
+ const gchar *property_name)
+{
+ const GDBusPropertyInfo *info;
+
+ if (proxy->priv->expected_interface == NULL)
+ return NULL;
+
+ info = g_dbus_interface_info_lookup_property (proxy->priv->expected_interface, property_name);
+ if (info == NULL)
+ {
+ g_warning ("Trying to lookup property %s which isn't in expected interface %s",
+ property_name,
+ proxy->priv->expected_interface->name);
+ }
+
+ return info;
+}
+
/**
* g_dbus_proxy_get_cached_property:
* @proxy: A #GDBusProxy.
* @property_name: Property name.
- * @error: Return location for error or %NULL.
- *
- * Looks up the value for a property from the cache. This call does no blocking IO.
*
- * Normally you will not need to modify the returned variant since it is updated automatically
- * in response to <literal>org.freedesktop.DBus.Properties.PropertiesChanged</literal>
- * D-Bus signals (which also causes #GDBusProxy::g-properties-changed to be emitted).
+ * Looks up the value for a property from the cache. This call does no
+ * blocking IO.
*
- * However, for properties for which said D-Bus signal is not emitted, you
- * can catch other signals and modify the returned variant accordingly (remember to emit
- * #GDBusProxy::g-properties-changed yourself).
+ * If @proxy has an expected interface (see
+ * #GDBusProxy:g-interface-info), then @property_name (for existence)
+ * is checked against it.
*
- * Returns: A reference to the #GVariant instance that holds the value for @property_name or
- * %NULL if @error is set. Free the reference with g_variant_unref().
+ * Returns: A reference to the #GVariant instance that holds the value
+ * for @property_name or %NULL if the value is not in the cache. The
+ * returned reference must be freed with g_variant_unref().
*
* Since: 2.26
*/
GVariant *
g_dbus_proxy_get_cached_property (GDBusProxy *proxy,
- const gchar *property_name,
- GError **error)
+ const gchar *property_name)
{
GVariant *value;
g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
g_return_val_if_fail (property_name != NULL, NULL);
- value = NULL;
-
- if (proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)
- {
- g_set_error (error,
- G_IO_ERROR,
- G_IO_ERROR_FAILED,
- _("Properties are not available (proxy created with G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)"));
- goto out;
- }
-
value = g_hash_table_lookup (proxy->priv->properties, property_name);
if (value == NULL)
{
- g_set_error (error,
- G_IO_ERROR,
- G_IO_ERROR_FAILED,
- _("No property with name %s"),
- property_name);
+ const GDBusPropertyInfo *info;
+ info = lookup_property_info_or_warn (proxy, property_name);
+ /* no difference */
goto out;
}
g_variant_ref (value);
out:
-
return value;
}
+/**
+ * g_dbus_proxy_set_cached_property:
+ * @proxy: A #GDBusProxy
+ * @property_name: Property name.
+ * @value: Value for the property or %NULL to remove it from the cache.
+ *
+ * If @value is not %NULL, sets the cached value for the property with
+ * name @property_name to the value in @value.
+ *
+ * If @value is %NULL, then the cached value is removed from the
+ * property cache.
+ *
+ * If @proxy has an expected interface (see
+ * #GDBusProxy:g-interface-info), then @property_name (for existence)
+ * and @value (for the type) is checked against it.
+ *
+ * If the @value #GVariant is floating, it is consumed. This allows
+ * convenient 'inline' use of g_variant_new(), e.g.
+ * |[
+ * g_dbus_proxy_set_cached_property (proxy,
+ * "SomeProperty",
+ * g_variant_new ("(si)",
+ * "A String",
+ * 42));
+ * ]|
+ *
+ * Normally you will not need to use this method since @proxy is
+ * tracking changes using the
+ * <literal>org.freedesktop.DBus.Properties.PropertiesChanged</literal>
+ * D-Bus signal. However, for performance reasons an object may decide
+ * to not use this signal for some properties and instead use a
+ * proprietary out-of-band mechanism to transmit changes.
+ *
+ * As a concrete example, consider an object with a property
+ * <literal>ChatroomParticipants</literal> which is an array of
+ * strings. Instead of transmitting the same (long) array every time
+ * the property changes, it is more efficient to only transmit the
+ * delta using e.g. signals <literal>ChatroomParticipantJoined(String
+ * name)</literal> and <literal>ChatroomParticipantParted(String
+ * name)</literal>.
+ *
+ * Since: 2.26
+ */
+void
+g_dbus_proxy_set_cached_property (GDBusProxy *proxy,
+ const gchar *property_name,
+ GVariant *value)
+{
+ const GDBusPropertyInfo *info;
+
+ g_return_if_fail (G_IS_DBUS_PROXY (proxy));
+ g_return_if_fail (property_name != NULL);
+
+ if (value != NULL)
+ {
+ info = lookup_property_info_or_warn (proxy, property_name);
+ if (info != NULL)
+ {
+ if (g_strcmp0 (info->signature, g_variant_get_type_string (value)) != 0)
+ {
+ g_warning (_("Trying to set property %s of type %s but according to the expected "
+ "interface the type is %s"),
+ property_name,
+ g_variant_get_type_string (value),
+ info->signature);
+ goto out;
+ }
+ }
+ g_hash_table_insert (proxy->priv->properties,
+ g_strdup (property_name),
+ g_variant_ref_sink (value));
+ }
+ else
+ {
+ g_hash_table_remove (proxy->priv->properties, property_name);
+ }
+
+ out:
+ ;
+}
+
/* ---------------------------------------------------------------------------------------------------- */
static void
{
const GDBusMethodInfo *info;
- if (!proxy->priv->expected_interface)
+ if (proxy->priv->expected_interface == NULL)
return NULL;
info = g_dbus_interface_info_lookup_method (proxy->priv->expected_interface, method_name);
- if (!info)
- g_warning ("Trying to invoke method %s which isn't in expected interface %s",
- method_name, proxy->priv->expected_interface->name);
+ if (info == NULL)
+ {
+ g_warning ("Trying to invoke method %s which isn't in expected interface %s",
+ method_name, proxy->priv->expected_interface->name);
+ }
return info;
}
if (proxy->priv->expected_interface)
{
expected_method_info = g_dbus_interface_info_lookup_method (proxy->priv->expected_interface, target_method_name);
- if (!expected_method_info)
- g_warning ("Trying to invoke method %s which isn't in expected interface %s",
- target_method_name, target_interface_name);
+ if (expected_method_info == NULL)
+ {
+ g_warning ("Trying to invoke method `%s' which isn't in expected interface `%s'",
+ target_method_name,
+ target_interface_name);
+ }
}
else
{
void g_dbus_proxy_set_interface_info (GDBusProxy *proxy,
GDBusInterfaceInfo *info);
GVariant *g_dbus_proxy_get_cached_property (GDBusProxy *proxy,
+ const gchar *property_name);
+void g_dbus_proxy_set_cached_property (GDBusProxy *proxy,
const gchar *property_name,
- GError **error);
+ GVariant *value);
gchar **g_dbus_proxy_get_cached_property_names (GDBusProxy *proxy,
GError **error);
void g_dbus_proxy_call (GDBusProxy *proxy,
g_dbus_proxy_new_finish
g_dbus_proxy_new_sync
g_dbus_proxy_get_cached_property
+g_dbus_proxy_set_cached_property
g_dbus_proxy_get_cached_property_names
g_dbus_proxy_get_connection
g_dbus_proxy_get_default_timeout
GVariant *value;
const gchar *ret;
g_return_val_if_fail (ACCOUNTS_IS_USER (user), NULL);
- value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (user), "UserName", NULL);
+ value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (user), "UserName");
ret = g_variant_get_string (value, NULL);
g_variant_unref (value);
return ret;
GVariant *value;
const gchar *ret;
g_return_val_if_fail (ACCOUNTS_IS_USER (user), NULL);
- value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (user), "RealName", NULL);
+ value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (user), "RealName");
ret = g_variant_get_string (value, NULL);
g_variant_unref (value);
return ret;
GVariant *value;
gboolean ret;
g_return_val_if_fail (ACCOUNTS_IS_USER (user), FALSE);
- value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (user), "AutomaticLogin", NULL);
+ value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (user), "AutomaticLogin");
ret = g_variant_get_boolean (value);
g_variant_unref (value);
return ret;
const gchar *key = property_names[n];
GVariant *value;
gchar *value_str;
- value = g_dbus_proxy_get_cached_property (proxy, key, NULL);
+ value = g_dbus_proxy_get_cached_property (proxy, key);
value_str = g_variant_print (value, TRUE);
g_print (" %s -> %s\n", key, value_str);
g_variant_unref (value);
g_assert_no_error (error);
g_assert (proxy != NULL);
error = NULL;
- value = g_dbus_proxy_get_cached_property (proxy, "PeerProperty", &error);
- g_assert_no_error (error);
+ value = g_dbus_proxy_get_cached_property (proxy, "PeerProperty");
g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "ThePropertyValue");
/* try invoking a method */
*
* No need to test all properties - GVariant has already been tested
*/
- variant = g_dbus_proxy_get_cached_property (proxy, "y", &error);
- g_assert_no_error (error);
+ variant = g_dbus_proxy_get_cached_property (proxy, "y");
g_assert (variant != NULL);
g_assert_cmpint (g_variant_get_byte (variant), ==, 1);
g_variant_unref (variant);
- variant = g_dbus_proxy_get_cached_property (proxy, "o", &error);
- g_assert_no_error (error);
+ variant = g_dbus_proxy_get_cached_property (proxy, "o");
g_assert (variant != NULL);
g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "/some/path");
g_variant_unref (variant);
g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
g_variant_unref (result);
_g_assert_signal_received (proxy, "g-properties-changed");
- variant = g_dbus_proxy_get_cached_property (proxy, "y", &error);
- g_assert_no_error (error);
+ variant = g_dbus_proxy_get_cached_property (proxy, "y");
g_assert (variant != NULL);
g_assert_cmpint (g_variant_get_byte (variant), ==, 42);
g_variant_unref (variant);
+
+ g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_byte (142));
+ variant = g_dbus_proxy_get_cached_property (proxy, "y");
+ g_assert (variant != NULL);
+ g_assert_cmpint (g_variant_get_byte (variant), ==, 142);
+ g_variant_unref (variant);
+
+ g_dbus_proxy_set_cached_property (proxy, "y", NULL);
+ variant = g_dbus_proxy_get_cached_property (proxy, "y");
+ g_assert (variant == NULL);
}
/* ---------------------------------------------------------------------------------------------------- */
" <method name='Sleep'>"
" <arg type='i' name='timeout' direction='in'/>"
" </method>"
+ " <property name='y' type='y' access='readwrite'/>"
" </interface>"
"</node>";
static GDBusInterfaceInfo *frob_dbus_interface_info;
test_properties (connection, name, name_owner, proxy);
test_signals (connection, name, name_owner, proxy);
+ /* This is obviously wrong but expected interface is not set so we don't fail... */
+ g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_string ("error_me_out!"));
+ g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_byte (42));
+ g_dbus_proxy_set_cached_property (proxy, "does-not-exist", g_variant_new_string ("something"));
+ g_dbus_proxy_set_cached_property (proxy, "does-not-exist", NULL);
+
/* Now repeat the method tests, with an expected interface set */
g_dbus_proxy_set_interface_info (proxy, frob_dbus_interface_info);
test_methods (connection, name, name_owner, proxy);
*/
test_bogus_method_return (connection, name, name_owner, proxy);
+ /* Also check that we complain if setting a cached property of the wrong type */
+ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
+ {
+ g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_string ("error_me_out!"));
+ }
+ g_test_trap_assert_stderr ("*Trying to set property y of type s but according to the expected interface the type is y*");
+ g_test_trap_assert_failed();
+
+ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
+ {
+ g_dbus_proxy_set_cached_property (proxy, "does-not-exist", g_variant_new_string ("something"));
+ }
+ g_test_trap_assert_stderr ("*Trying to lookup property does-not-exist which isn't in expected interface com.example.Frob*");
+ g_test_trap_assert_failed();
+
+ /* this should work, however (since the type is correct) */
+ g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_byte (42));
+
g_main_loop_quit (loop);
}