/*
* e-gdbus-templates.c
*
* Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
*
* This library is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see .
*
*/
#include
#include
#include "e-data-server-util.h"
#include "e-flag.h"
#include "e-gdbus-templates.h"
static GThread *main_thread = NULL;
void
e_gdbus_templates_init_main_thread (void)
{
if (!main_thread) {
main_thread = g_thread_self ();
} else if (main_thread != g_thread_self ()) {
g_warning ("%s: Called in different main thread, stored: %p would use: %p", G_STRFUNC, main_thread, g_thread_self ());
}
}
gboolean
e_gdbus_signal_emission_hook_void (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
const gchar *signal_name,
const gchar *iface_name)
{
GObject *object;
GDBusConnection *connection;
const gchar *path;
if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
return FALSE;
object = g_value_get_object (¶m_values[0]);
path = g_object_get_data (object, "gdbus-codegen-path");
connection = g_object_get_data (object, "gdbus-codegen-connection");
if (connection == NULL || path == NULL)
return FALSE;
g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, NULL, NULL);
return TRUE;
}
gboolean
e_gdbus_signal_emission_hook_boolean (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
const gchar *signal_name,
const gchar *iface_name)
{
GObject *object;
GDBusConnection *connection;
const gchar *path;
GVariant *params;
GVariant *item;
GVariantBuilder *builder;
if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
return FALSE;
object = g_value_get_object (¶m_values[0]);
path = g_object_get_data (object, "gdbus-codegen-path");
connection = g_object_get_data (object, "gdbus-codegen-connection");
if (connection == NULL || path == NULL)
return FALSE;
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
g_return_val_if_fail (n_param_values - 1 == 1, FALSE);
param_values++;
item = g_variant_new_boolean (g_value_get_boolean (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
params = g_variant_builder_end (builder);
g_variant_builder_unref (builder);
g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
return TRUE;
}
gboolean
e_gdbus_signal_emission_hook_string (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
const gchar *signal_name,
const gchar *iface_name)
{
GObject *object;
GDBusConnection *connection;
const gchar *path;
GVariant *params;
GVariant *item;
GVariantBuilder *builder;
if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
return FALSE;
object = g_value_get_object (¶m_values[0]);
path = g_object_get_data (object, "gdbus-codegen-path");
connection = g_object_get_data (object, "gdbus-codegen-connection");
if (connection == NULL || path == NULL)
return FALSE;
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
g_return_val_if_fail (n_param_values - 1 == 1, FALSE);
param_values++;
item = g_variant_new_string (g_value_get_string (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
params = g_variant_builder_end (builder);
g_variant_builder_unref (builder);
g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
return TRUE;
}
gboolean
e_gdbus_signal_emission_hook_strv (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
const gchar *signal_name,
const gchar *iface_name)
{
GObject *object;
GDBusConnection *connection;
const gchar *path;
GVariant *params;
GVariant *item;
GVariantBuilder *builder;
const gchar * const *arg_strv;
if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
return FALSE;
object = g_value_get_object (¶m_values[0]);
path = g_object_get_data (object, "gdbus-codegen-path");
connection = g_object_get_data (object, "gdbus-codegen-connection");
if (connection == NULL || path == NULL)
return FALSE;
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
g_return_val_if_fail (n_param_values - 1 == 1, FALSE);
param_values++;
arg_strv = g_value_get_boxed (param_values);
item = g_variant_new_strv (arg_strv, -1);
g_variant_builder_add_value (builder, item);
param_values++;
params = g_variant_builder_end (builder);
g_variant_builder_unref (builder);
g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
return TRUE;
}
gboolean
e_gdbus_signal_emission_hook_uint (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
const gchar *signal_name,
const gchar *iface_name)
{
GObject *object;
GDBusConnection *connection;
const gchar *path;
GVariant *params;
GVariant *item;
GVariantBuilder *builder;
if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
return FALSE;
object = g_value_get_object (¶m_values[0]);
path = g_object_get_data (object, "gdbus-codegen-path");
connection = g_object_get_data (object, "gdbus-codegen-connection");
if (connection == NULL || path == NULL)
return FALSE;
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
g_return_val_if_fail (n_param_values - 1 == 1, FALSE);
param_values++;
item = g_variant_new_uint32 (g_value_get_uint (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
params = g_variant_builder_end (builder);
g_variant_builder_unref (builder);
g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
return TRUE;
}
gboolean
e_gdbus_signal_emission_hook_uint_string (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
const gchar *signal_name,
const gchar *iface_name)
{
GObject *object;
GDBusConnection *connection;
const gchar *path;
GVariant *params;
GVariant *item;
GVariantBuilder *builder;
if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
return FALSE;
object = g_value_get_object (¶m_values[0]);
path = g_object_get_data (object, "gdbus-codegen-path");
connection = g_object_get_data (object, "gdbus-codegen-connection");
if (connection == NULL || path == NULL)
return FALSE;
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
g_return_val_if_fail (n_param_values - 1 == 2, FALSE);
param_values++;
item = g_variant_new_uint32 (g_value_get_uint (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
item = g_variant_new_string (g_value_get_string (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
params = g_variant_builder_end (builder);
g_variant_builder_unref (builder);
g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
return TRUE;
}
gboolean
e_gdbus_signal_emission_hook_async_void (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
const gchar *signal_name,
const gchar *iface_name)
{
GObject *object;
GDBusConnection *connection;
const gchar *path;
GVariant *params;
GVariant *item;
GVariantBuilder *builder;
GError *arg_error;
if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
return FALSE;
object = g_value_get_object (¶m_values[0]);
path = g_object_get_data (object, "gdbus-codegen-path");
connection = g_object_get_data (object, "gdbus-codegen-connection");
if (connection == NULL || path == NULL)
return FALSE;
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
g_return_val_if_fail (n_param_values - 1 == 2, FALSE);
param_values++;
item = g_variant_new_uint32 (g_value_get_uint (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
arg_error = g_value_get_boxed (param_values);
if (arg_error) {
gchar *dbus_error_name = g_dbus_error_encode_gerror (arg_error);
item = g_variant_new_string (dbus_error_name ? dbus_error_name : "");
g_variant_builder_add_value (builder, item);
item = g_variant_new_string (arg_error->message);
g_variant_builder_add_value (builder, item);
g_free (dbus_error_name);
} else {
item = g_variant_new_string ("");
g_variant_builder_add_value (builder, item);
item = g_variant_new_string ("");
g_variant_builder_add_value (builder, item);
param_values++;
}
params = g_variant_builder_end (builder);
g_variant_builder_unref (builder);
g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
return TRUE;
}
gboolean
e_gdbus_signal_emission_hook_async_boolean (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
const gchar *signal_name,
const gchar *iface_name)
{
GObject *object;
GDBusConnection *connection;
const gchar *path;
GVariant *params;
GVariant *item;
GVariantBuilder *builder;
GError *arg_error;
if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
return FALSE;
object = g_value_get_object (¶m_values[0]);
path = g_object_get_data (object, "gdbus-codegen-path");
connection = g_object_get_data (object, "gdbus-codegen-connection");
if (connection == NULL || path == NULL)
return FALSE;
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
g_return_val_if_fail (n_param_values - 1 == 3, FALSE);
param_values++;
item = g_variant_new_uint32 (g_value_get_uint (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
arg_error = g_value_get_boxed (param_values);
if (arg_error) {
gchar *dbus_error_name = g_dbus_error_encode_gerror (arg_error);
item = g_variant_new_string (dbus_error_name ? dbus_error_name : "");
g_variant_builder_add_value (builder, item);
item = g_variant_new_string (arg_error->message);
g_variant_builder_add_value (builder, item);
g_free (dbus_error_name);
/* fake value for easier processing in e_gdbus_proxy_emit_signal() */
item = g_variant_new_boolean (FALSE);
g_variant_builder_add_value (builder, item);
} else {
item = g_variant_new_string ("");
g_variant_builder_add_value (builder, item);
item = g_variant_new_string ("");
g_variant_builder_add_value (builder, item);
param_values++;
item = g_variant_new_boolean (g_value_get_boolean (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
}
params = g_variant_builder_end (builder);
g_variant_builder_unref (builder);
g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
return TRUE;
}
gboolean
e_gdbus_signal_emission_hook_async_string (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
const gchar *signal_name,
const gchar *iface_name)
{
GObject *object;
GDBusConnection *connection;
const gchar *path;
GVariant *params;
GVariant *item;
GVariantBuilder *builder;
GError *arg_error;
if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
return FALSE;
object = g_value_get_object (¶m_values[0]);
path = g_object_get_data (object, "gdbus-codegen-path");
connection = g_object_get_data (object, "gdbus-codegen-connection");
if (connection == NULL || path == NULL)
return FALSE;
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
g_return_val_if_fail (n_param_values - 1 == 3, FALSE);
param_values++;
item = g_variant_new_uint32 (g_value_get_uint (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
arg_error = g_value_get_boxed (param_values);
if (arg_error) {
gchar *dbus_error_name = g_dbus_error_encode_gerror (arg_error);
item = g_variant_new_string (dbus_error_name ? dbus_error_name : "");
g_variant_builder_add_value (builder, item);
item = g_variant_new_string (arg_error->message);
g_variant_builder_add_value (builder, item);
g_free (dbus_error_name);
/* fake value for easier processing in e_gdbus_proxy_emit_signal() */
item = g_variant_new_string ("");
g_variant_builder_add_value (builder, item);
} else {
item = g_variant_new_string ("");
g_variant_builder_add_value (builder, item);
item = g_variant_new_string ("");
g_variant_builder_add_value (builder, item);
param_values++;
item = g_variant_new_string (g_value_get_string (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
}
params = g_variant_builder_end (builder);
g_variant_builder_unref (builder);
g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
return TRUE;
}
gboolean
e_gdbus_signal_emission_hook_async_strv (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
const gchar *signal_name,
const gchar *iface_name)
{
GObject *object;
GDBusConnection *connection;
const gchar *path;
GVariant *params;
GVariant *item;
GVariantBuilder *builder;
const GError *arg_error;
const gchar * const *arg_strv;
if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
return FALSE;
object = g_value_get_object (¶m_values[0]);
path = g_object_get_data (object, "gdbus-codegen-path");
connection = g_object_get_data (object, "gdbus-codegen-connection");
if (connection == NULL || path == NULL)
return FALSE;
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
g_return_val_if_fail (n_param_values - 1 == 3, FALSE);
param_values++;
item = g_variant_new_uint32 (g_value_get_uint (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
arg_error = g_value_get_boxed (param_values);
if (arg_error) {
const gchar *fake_strv;
gchar *dbus_error_name = g_dbus_error_encode_gerror (arg_error);
item = g_variant_new_string (dbus_error_name ? dbus_error_name : "");
g_variant_builder_add_value (builder, item);
item = g_variant_new_string (arg_error->message);
g_variant_builder_add_value (builder, item);
g_free (dbus_error_name);
/* fake value for easier processing in e_gdbus_proxy_emit_signal() */
fake_strv = NULL;
item = g_variant_new_strv (&fake_strv, -1);
g_variant_builder_add_value (builder, item);
} else {
item = g_variant_new_string ("");
g_variant_builder_add_value (builder, item);
item = g_variant_new_string ("");
g_variant_builder_add_value (builder, item);
param_values++;
arg_strv = g_value_get_boxed (param_values);
item = g_variant_new_strv (arg_strv, -1);
g_variant_builder_add_value (builder, item);
param_values++;
}
params = g_variant_builder_end (builder);
g_variant_builder_unref (builder);
g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
return TRUE;
}
gboolean
e_gdbus_signal_emission_hook_async_uint (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
const gchar *signal_name,
const gchar *iface_name)
{
GObject *object;
GDBusConnection *connection;
const gchar *path;
GVariant *params;
GVariant *item;
GVariantBuilder *builder;
GError *arg_error;
if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
return FALSE;
object = g_value_get_object (¶m_values[0]);
path = g_object_get_data (object, "gdbus-codegen-path");
connection = g_object_get_data (object, "gdbus-codegen-connection");
if (connection == NULL || path == NULL)
return FALSE;
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
g_return_val_if_fail (n_param_values - 1 == 3, FALSE);
param_values++;
item = g_variant_new_uint32 (g_value_get_uint (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
arg_error = g_value_get_boxed (param_values);
if (arg_error) {
gchar *dbus_error_name = g_dbus_error_encode_gerror (arg_error);
item = g_variant_new_string (dbus_error_name ? dbus_error_name : "");
g_variant_builder_add_value (builder, item);
item = g_variant_new_string (arg_error->message);
g_variant_builder_add_value (builder, item);
g_free (dbus_error_name);
/* fake value for easier processing in e_gdbus_proxy_emit_signal() */
item = g_variant_new_uint32 (g_value_get_uint (0));
g_variant_builder_add_value (builder, item);
} else {
item = g_variant_new_string ("");
g_variant_builder_add_value (builder, item);
item = g_variant_new_string ("");
g_variant_builder_add_value (builder, item);
param_values++;
item = g_variant_new_uint32 (g_value_get_uint (param_values));
g_variant_builder_add_value (builder, item);
param_values++;
}
params = g_variant_builder_end (builder);
g_variant_builder_unref (builder);
g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
return TRUE;
}
void
e_gdbus_proxy_emit_signal (GDBusProxy *proxy,
GVariant *parameters,
guint signal_id,
guint signal_type)
{
gboolean arg_boolean = FALSE;
const gchar *arg_const_string = NULL;
const gchar **arg_const_strv = NULL;
guint arg_uint = 0;
g_return_if_fail (proxy != NULL);
if ((signal_type & E_GDBUS_TYPE_IS_ASYNC) != 0) {
/* the signal is a done signal, thus opid and error name with error message are first two parameters */
guint arg_opid = 0;
const gchar *dbus_error_name = NULL, *dbus_error_message = NULL;
GError *arg_error = NULL;
signal_type = signal_type & (~E_GDBUS_TYPE_IS_ASYNC);
switch (signal_type) {
case E_GDBUS_TYPE_VOID:
g_variant_get (parameters, "(u&s&s)", &arg_opid, &dbus_error_name, &dbus_error_message);
break;
case E_GDBUS_TYPE_BOOLEAN:
g_variant_get (parameters, "(u&s&sb)", &arg_opid, &dbus_error_name, &dbus_error_message, &arg_boolean);
break;
case E_GDBUS_TYPE_STRING:
g_variant_get (parameters, "(u&s&s&s)", &arg_opid, &dbus_error_name, &dbus_error_message, &arg_const_string);
break;
case E_GDBUS_TYPE_STRV:
/* array is newly allocated, but items are gvariant's */
g_variant_get (parameters, "(u&s&s^a&s)", &arg_opid, &dbus_error_name, &dbus_error_message, &arg_const_strv);
break;
case E_GDBUS_TYPE_UINT:
g_variant_get (parameters, "(u&s&su)", &arg_opid, &dbus_error_name, &dbus_error_message, &arg_uint);
break;
default:
/* fix below too, if this is reached */
g_warning ("%s: Unknown E_GDBUS_TYPE %x", G_STRFUNC, signal_type);
return;
}
if (dbus_error_name && *dbus_error_name && dbus_error_message)
arg_error = g_dbus_error_new_for_dbus_error (dbus_error_name, dbus_error_message);
switch (signal_type) {
case E_GDBUS_TYPE_VOID:
g_signal_emit (proxy, signal_id, 0, arg_opid, arg_error);
break;
case E_GDBUS_TYPE_BOOLEAN:
g_signal_emit (proxy, signal_id, 0, arg_opid, arg_error, arg_boolean);
break;
case E_GDBUS_TYPE_STRING:
g_signal_emit (proxy, signal_id, 0, arg_opid, arg_error, arg_const_string);
break;
case E_GDBUS_TYPE_STRV:
g_signal_emit (proxy, signal_id, 0, arg_opid, arg_error, arg_const_strv);
g_free (arg_const_strv);
break;
case E_GDBUS_TYPE_UINT:
g_signal_emit (proxy, signal_id, 0, arg_opid, arg_error, arg_uint);
break;
}
if (arg_error)
g_error_free (arg_error);
} else {
switch (signal_type) {
case E_GDBUS_TYPE_VOID:
g_signal_emit (proxy, signal_id, 0);
break;
case E_GDBUS_TYPE_BOOLEAN:
g_variant_get (parameters, "(b)", &arg_boolean);
g_signal_emit (proxy, signal_id, 0, arg_boolean);
break;
case E_GDBUS_TYPE_STRING:
g_variant_get (parameters, "(&s)", &arg_const_string);
g_signal_emit (proxy, signal_id, 0, arg_const_string);
break;
case E_GDBUS_TYPE_STRV:
/* array is newly allocated, but items are gvariant's */
g_variant_get (parameters, "(^a&s)", &arg_const_strv);
g_signal_emit (proxy, signal_id, 0, arg_const_strv);
g_free (arg_const_strv);
break;
case E_GDBUS_TYPE_UINT:
g_variant_get (parameters, "(u)", &arg_uint);
g_signal_emit (proxy, signal_id, 0, arg_uint);
break;
case E_GDBUS_TYPE_UINT | E_GDBUS_TYPE_STRING:
g_variant_get (parameters, "(u&s)", &arg_uint, &arg_const_string);
g_signal_emit (proxy, signal_id, 0, arg_uint, arg_const_string);
break;
default:
g_warning ("%s: Unknown E_GDBUS_TYPE %x", G_STRFUNC, signal_type);
break;
}
}
}
void
e_gdbus_stub_handle_method_call (GObject *stub_object,
GDBusMethodInvocation *invocation,
GVariant *parameters,
const gchar *method_name,
guint method_id,
guint method_type)
{
gboolean handled = FALSE;
gboolean arg_boolean = FALSE;
const gchar *arg_const_string = NULL;
const gchar ** arg_const_strv = NULL;
guint arg_uint = 0;
g_return_if_fail (stub_object != NULL);
g_return_if_fail (method_name != NULL);
switch (method_type & (~E_GDBUS_TYPE_IS_ASYNC)) {
case E_GDBUS_TYPE_VOID:
g_signal_emit (stub_object, method_id, 0, invocation, &handled);
break;
case E_GDBUS_TYPE_BOOLEAN:
g_variant_get (parameters, "(b)", &arg_boolean);
g_signal_emit (stub_object, method_id, 0, invocation, arg_boolean, &handled);
break;
case E_GDBUS_TYPE_STRING:
g_variant_get (parameters, "(&s)", &arg_const_string);
g_signal_emit (stub_object, method_id, 0, invocation, arg_const_string, &handled);
break;
case E_GDBUS_TYPE_STRV:
/* array is newly allocated, but items are gvariant's */
g_variant_get (parameters, "(^a&s)", &arg_const_strv);
g_signal_emit (stub_object, method_id, 0, invocation, arg_const_strv, &handled);
g_free (arg_const_strv);
break;
case E_GDBUS_TYPE_UINT:
g_variant_get (parameters, "(u)", &arg_uint);
g_signal_emit (stub_object, method_id, 0, invocation, arg_uint, &handled);
break;
default:
g_warning ("%s: Unknown E_GDBUS_TYPE %x", G_STRFUNC, method_type);
break;
}
if (!handled)
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "Method `%s' is not implemented", method_name);
}
G_DEFINE_INTERFACE (EGdbusAsyncOpKeeper, e_gdbus_async_op_keeper, G_TYPE_OBJECT)
static void
e_gdbus_async_op_keeper_default_init (EGdbusAsyncOpKeeperInterface *iface)
{
}
/**
* e_gdbus_async_op_keeper_create_pending_ops:
* @object: a #EGdbusAsyncOpKeeper
*
* Create a hash table of pending async operations. This can be freed
* with g_hash_table_unref() in dispose. The interface asks for this
* pointer by calling e_gdbus_async_op_keeper_create_pending_ops().
*
* Returns: (transfer full) (element-type gpointer gpointer): hash table of
* pending async operations; free with g_hash_table_unref()
*/
GHashTable *
e_gdbus_async_op_keeper_create_pending_ops (EGdbusAsyncOpKeeper *object)
{
g_return_val_if_fail (object != NULL, NULL);
g_return_val_if_fail (E_IS_GDBUS_ASYNC_OP_KEEPER (object), NULL);
return g_hash_table_new (g_direct_hash, g_direct_equal);
}
/**
* e_gdbus_async_op_keeper_get_pending_ops:
* @object: a #EGdbusAsyncOpKeeper
*
* Get the hash table of pending async operations previously created
* by e_gdbus_async_op_keeper_create_pending_ops().
*
* Returns: (transfer none): hash table of pending async operations
*/
GHashTable *
e_gdbus_async_op_keeper_get_pending_ops (EGdbusAsyncOpKeeper *object)
{
EGdbusAsyncOpKeeperInterface *iface;
g_return_val_if_fail (E_IS_GDBUS_ASYNC_OP_KEEPER (object), NULL);
iface = E_GDBUS_ASYNC_OP_KEEPER_GET_IFACE (object);
g_return_val_if_fail (iface->get_pending_ops != NULL, NULL);
return iface->get_pending_ops (object);
}
/* synchronously cancels one operation - sends a request from client to the server */
gboolean
e_gdbus_async_op_keeper_cancel_op_sync (EGdbusAsyncOpKeeper *object,
guint in_opid,
GCancellable *cancellable,
GError **error)
{
EGdbusAsyncOpKeeperInterface *iface;
g_return_val_if_fail (E_IS_GDBUS_ASYNC_OP_KEEPER (object), FALSE);
iface = E_GDBUS_ASYNC_OP_KEEPER_GET_IFACE (object);
g_return_val_if_fail (iface->cancel_op_sync != NULL, FALSE);
return iface->cancel_op_sync (object, in_opid, cancellable, error);
}
/* Used to finish asynchronous GDBus call - this might be done in the callback
* as soon as possible; method returns to a caller operation ID which was started */
void
e_gdbus_complete_async_method (gpointer object,
GDBusMethodInvocation *invocation,
guint opid)
{
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", opid));
}
/* Used to finish synchronous GDBus call - this might be done in the callback
* as soon as possible */
void
e_gdbus_complete_sync_method_void (gpointer object,
GDBusMethodInvocation *invocation,
const GError *error)
{
if (error)
g_dbus_method_invocation_return_gerror (invocation, error);
else
g_dbus_method_invocation_return_value (invocation, NULL);
}
void
e_gdbus_complete_sync_method_boolean (gpointer object,
GDBusMethodInvocation *invocation,
gboolean out_boolean,
const GError *error)
{
if (error)
g_dbus_method_invocation_return_gerror (invocation, error);
else
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", out_boolean));
}
void
e_gdbus_complete_sync_method_string (gpointer object,
GDBusMethodInvocation *invocation,
const gchar *out_string,
const GError *error)
{
if (error)
g_dbus_method_invocation_return_gerror (invocation, error);
else
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", out_string));
}
void
e_gdbus_complete_sync_method_strv (gpointer object,
GDBusMethodInvocation *invocation,
const gchar * const *out_strv,
const GError *error)
{
if (error)
g_dbus_method_invocation_return_gerror (invocation, error);
else
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(^as)", out_strv));
}
void
e_gdbus_complete_sync_method_uint (gpointer object,
GDBusMethodInvocation *invocation,
guint out_uint,
const GError *error)
{
if (error)
g_dbus_method_invocation_return_gerror (invocation, error);
else
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", out_uint));
}
typedef struct _AsyncOpData
{
gint ref_count;
EGdbusAsyncOpKeeper *proxy;
guint opid;
GCancellable *cancellable;
gulong cancel_id;
guint cancel_idle_id;
gpointer async_source_tag;
GAsyncReadyCallback async_callback;
gpointer async_user_data;
guint result_type; /* any of E_GDBUS_TYPE_... except of E_GDBUS_TYPE_IS_ASYNC */
union {
gboolean out_boolean;
gchar *out_string;
gchar ** out_strv;
guint out_uint;
} result;
} AsyncOpData;
static void
async_op_data_free (AsyncOpData *op_data)
{
GHashTable *pending_ops;
g_return_if_fail (op_data != NULL);
pending_ops = e_gdbus_async_op_keeper_get_pending_ops (op_data->proxy);
if (op_data->cancel_idle_id) {
GError *error = NULL;
g_source_remove (op_data->cancel_idle_id);
op_data->cancel_idle_id = 0;
if (pending_ops)
g_hash_table_remove (pending_ops, GUINT_TO_POINTER (op_data->opid));
if (!e_gdbus_async_op_keeper_cancel_op_sync (op_data->proxy, op_data->opid, NULL, &error)) {
g_debug ("%s: Failed to cancel operation: %s\n", G_STRFUNC, error ? error->message : "Unknown error");
g_clear_error (&error);
}
} else if (pending_ops) {
g_hash_table_remove (pending_ops, GUINT_TO_POINTER (op_data->opid));
}
if (op_data->cancellable) {
if (op_data->cancel_id) {
g_cancellable_disconnect (op_data->cancellable, op_data->cancel_id);
op_data->cancel_id = 0;
}
g_object_unref (op_data->cancellable);
op_data->cancellable = NULL;
}
if (!g_atomic_int_dec_and_test (&op_data->ref_count))
return;
g_object_unref (op_data->proxy);
switch (op_data->result_type) {
case E_GDBUS_TYPE_STRING:
if (op_data->result.out_string)
g_free (op_data->result.out_string);
break;
case E_GDBUS_TYPE_STRV:
if (op_data->result.out_strv)
g_strfreev (op_data->result.out_strv);
break;
}
g_free (op_data);
g_return_if_fail (pending_ops != NULL);
}
static void
async_op_complete (AsyncOpData *op_data,
const GError *error,
gboolean in_idle)
{
GSimpleAsyncResult *simple;
g_return_if_fail (op_data != NULL);
g_atomic_int_inc (&op_data->ref_count);
simple = g_simple_async_result_new (G_OBJECT (op_data->proxy), op_data->async_callback, op_data->async_user_data, op_data->async_source_tag);
g_simple_async_result_set_op_res_gpointer (simple, op_data, (GDestroyNotify) async_op_data_free);
if (error)
g_simple_async_result_set_from_error (simple, error);
if (in_idle)
g_simple_async_result_complete_in_idle (simple);
else
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
typedef struct _CancelData
{
EGdbusAsyncOpKeeper *proxy;
guint opid;
AsyncOpData *op_data;
} CancelData;
static void
cancel_data_free (gpointer ptr)
{
CancelData *cd = ptr;
if (!cd)
return;
g_object_unref (cd->proxy);
g_free (cd);
}
static gboolean
e_gdbus_op_cancelled_idle_cb (gpointer user_data)
{
CancelData *cd = user_data;
AsyncOpData *op_data;
GHashTable *pending_ops;
GCancellable *cancellable;
GError *error = NULL;
g_return_val_if_fail (cd != NULL, FALSE);
pending_ops = e_gdbus_async_op_keeper_get_pending_ops (cd->proxy);
if (pending_ops && !g_hash_table_lookup (pending_ops, GUINT_TO_POINTER (cd->opid))) {
/* got served already */
return FALSE;
}
op_data = cd->op_data;
g_return_val_if_fail (op_data != NULL, FALSE);
cancellable = op_data->cancellable;
op_data->cancel_idle_id = 0;
if (!e_gdbus_async_op_keeper_cancel_op_sync (op_data->proxy, op_data->opid, NULL, &error)) {
g_debug ("%s: Failed to cancel operation: %s\n", G_STRFUNC, error ? error->message : "Unknown error");
g_clear_error (&error);
}
g_return_val_if_fail (g_cancellable_set_error_if_cancelled (cancellable, &error), FALSE);
async_op_complete (op_data, error, TRUE);
g_clear_error (&error);
return FALSE;
}
static void
e_gdbus_op_cancelled_cb (GCancellable *cancellable,
AsyncOpData *op_data)
{
CancelData *cd;
g_return_if_fail (op_data != NULL);
g_return_if_fail (op_data->cancellable == cancellable);
cd = g_new0 (CancelData, 1);
cd->proxy = g_object_ref (op_data->proxy);
cd->opid = op_data->opid;
cd->op_data = op_data;
/* do this on idle, because this callback should be left
* as soon as possible, with no sync calls being done;
* also schedule with priority higher than gtk+ uses
* for animations (check docs for G_PRIORITY_HIGH_IDLE) */
op_data->cancel_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT, e_gdbus_op_cancelled_idle_cb, cd, cancel_data_free);
}
static void
e_gdbus_async_call_opid_ready_cb (GObject *source_proxy,
GAsyncResult *result,
gpointer user_data)
{
GVariant *_result;
GError *error = NULL;
AsyncOpData *op_data = user_data;
_result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_proxy), result, &error);
if (_result != NULL && !error) {
EGdbusAsyncOpKeeper *op_keeper = E_GDBUS_ASYNC_OP_KEEPER (source_proxy);
GHashTable *pending_ops;
gboolean add_pending = TRUE;
g_return_if_fail (op_keeper != NULL);
pending_ops = e_gdbus_async_op_keeper_get_pending_ops (op_keeper);
g_return_if_fail (pending_ops != NULL);
g_variant_get (_result, "(u)", &op_data->opid);
g_variant_unref (_result);
if (op_data->cancellable && !g_cancellable_set_error_if_cancelled (op_data->cancellable, &error))
op_data->cancel_id = g_cancellable_connect (op_data->cancellable, G_CALLBACK (e_gdbus_op_cancelled_cb), op_data, NULL);
else
add_pending = op_data->cancellable == NULL;
/* add to pending ops, waiting for associated 'done' signal */
if (add_pending)
g_hash_table_insert (pending_ops, GUINT_TO_POINTER (op_data->opid), op_data);
} else if (_result) {
g_variant_unref (_result);
}
if (error) {
async_op_complete (op_data, error, FALSE);
g_error_free (error);
}
}
static gchar **
copy_strv (const gchar * const *strv)
{
GPtrArray *array;
gint ii;
array = g_ptr_array_sized_new (g_strv_length ((gchar **) strv) + 1);
for (ii = 0; strv[ii]; ii++) {
g_ptr_array_add (array, g_strdup (strv[ii]));
}
/* NULL-terminated */
g_ptr_array_add (array, NULL);
return (gchar **) g_ptr_array_free (array, FALSE);
}
static void
e_gdbus_proxy_async_method_done (guint e_gdbus_type,
gconstpointer out_value,
EGdbusAsyncOpKeeper *object,
guint arg_opid,
const GError *error)
{
AsyncOpData *op_data;
GHashTable *pending_ops;
g_return_if_fail (object != NULL);
g_return_if_fail (E_IS_GDBUS_ASYNC_OP_KEEPER (object));
pending_ops = e_gdbus_async_op_keeper_get_pending_ops (object);
g_return_if_fail (pending_ops != NULL);
op_data = g_hash_table_lookup (pending_ops, GUINT_TO_POINTER (arg_opid));
if (!op_data) {
/* it happens for cancelled operations, thus rather than track cancelled ops disable the debug warning */
/* g_debug ("%s: Operation %d gone before got done signal for it", G_STRFUNC, arg_opid); */
return;
}
if (out_value) {
op_data->result_type = e_gdbus_type;
switch (e_gdbus_type) {
case E_GDBUS_TYPE_VOID:
break;
case E_GDBUS_TYPE_BOOLEAN:
op_data->result.out_boolean = * ((const gboolean *) out_value);
break;
case E_GDBUS_TYPE_STRING:
op_data->result.out_string = g_strdup ((const gchar *) out_value);
break;
case E_GDBUS_TYPE_STRV:
op_data->result.out_strv = copy_strv ((const gchar * const *) out_value);
break;
case E_GDBUS_TYPE_UINT:
op_data->result.out_uint = * ((const guint *) out_value);
break;
default:
g_warning ("%s: Unknown E_GDBUS_TYPE %x", G_STRFUNC, e_gdbus_type);
break;
}
}
async_op_complete (op_data, error, TRUE);
}
void
e_gdbus_proxy_async_method_done_void (EGdbusAsyncOpKeeper *proxy,
guint arg_opid,
const GError *error)
{
e_gdbus_proxy_async_method_done (E_GDBUS_TYPE_VOID, NULL, proxy, arg_opid, error);
}
void
e_gdbus_proxy_async_method_done_boolean (EGdbusAsyncOpKeeper *proxy,
guint arg_opid,
const GError *error,
gboolean out_boolean)
{
e_gdbus_proxy_async_method_done (E_GDBUS_TYPE_BOOLEAN, &out_boolean, proxy, arg_opid, error);
}
/* takes ownership of the out parameter */
void
e_gdbus_proxy_async_method_done_string (EGdbusAsyncOpKeeper *proxy,
guint arg_opid,
const GError *error,
const gchar *out_string)
{
e_gdbus_proxy_async_method_done (E_GDBUS_TYPE_STRING, out_string, proxy, arg_opid, error);
}
/* takes ownership of the out parameter */
void
e_gdbus_proxy_async_method_done_strv (EGdbusAsyncOpKeeper *proxy,
guint arg_opid,
const GError *error,
const gchar * const *out_strv)
{
e_gdbus_proxy_async_method_done (E_GDBUS_TYPE_STRV, out_strv, proxy, arg_opid, error);
}
void
e_gdbus_proxy_async_method_done_uint (EGdbusAsyncOpKeeper *proxy,
guint arg_opid,
const GError *error,
guint out_uint)
{
e_gdbus_proxy_async_method_done (E_GDBUS_TYPE_UINT, &out_uint, proxy, arg_opid, error);
}
/* takes ownership of _params */
static void
e_gdbus_proxy_call_with_params (GVariant *_params,
const gchar *method_name,
gpointer source_tag,
EGdbusAsyncOpKeeper *proxy,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
AsyncOpData *op_data;
op_data = g_new0 (AsyncOpData, 1);
op_data->proxy = g_object_ref (proxy);
op_data->opid = 0;
op_data->async_source_tag = source_tag;
op_data->async_callback = callback;
op_data->async_user_data = user_data;
op_data->cancellable = cancellable;
if (op_data->cancellable)
g_object_ref (op_data->cancellable);
g_dbus_proxy_call (G_DBUS_PROXY (proxy), method_name, _params, G_DBUS_CALL_FLAGS_NONE, e_data_server_util_get_dbus_call_timeout (), cancellable, e_gdbus_async_call_opid_ready_cb, op_data);
}
void
e_gdbus_proxy_call_void (const gchar *method_name,
gpointer source_tag,
EGdbusAsyncOpKeeper *proxy,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
e_gdbus_proxy_call_with_params (NULL, method_name, source_tag, proxy, cancellable, callback, user_data);
}
void
e_gdbus_proxy_call_boolean (const gchar *method_name,
gpointer source_tag,
EGdbusAsyncOpKeeper *proxy,
gboolean in_boolean,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GVariant *_params;
_params = g_variant_new ("(b)", in_boolean);
e_gdbus_proxy_call_with_params (_params, method_name, source_tag, proxy, cancellable, callback, user_data);
}
void
e_gdbus_proxy_call_string (const gchar *method_name,
gpointer source_tag,
EGdbusAsyncOpKeeper *proxy,
const gchar *in_string,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GVariant *_params;
_params = g_variant_new ("(s)", in_string);
e_gdbus_proxy_call_with_params (_params, method_name, source_tag, proxy, cancellable, callback, user_data);
}
void
e_gdbus_proxy_call_strv (const gchar *method_name,
gpointer source_tag,
EGdbusAsyncOpKeeper *proxy,
const gchar * const *in_strv,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GVariant *_params;
_params = g_variant_new ("(^as)", in_strv);
e_gdbus_proxy_call_with_params (_params, method_name, source_tag, proxy, cancellable, callback, user_data);
}
void
e_gdbus_proxy_call_uint (const gchar *method_name,
gpointer source_tag,
EGdbusAsyncOpKeeper *proxy,
guint in_uint,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GVariant *_params;
_params = g_variant_new ("(u)", in_uint);
e_gdbus_proxy_call_with_params (_params, method_name, source_tag, proxy, cancellable, callback, user_data);
}
gboolean
e_gdbus_proxy_finish_call_void (EGdbusAsyncOpKeeper *proxy,
GAsyncResult *result,
GError **error,
gpointer source_tag)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), source_tag), FALSE);
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
}
gboolean
e_gdbus_proxy_finish_call_boolean (EGdbusAsyncOpKeeper *proxy,
GAsyncResult *result,
gboolean *out_boolean,
GError **error,
gpointer source_tag)
{
AsyncOpData *op_data;
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), source_tag), FALSE);
g_return_val_if_fail (out_boolean != NULL, FALSE);
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
return FALSE;
op_data = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
g_return_val_if_fail (op_data != NULL, FALSE);
g_return_val_if_fail (op_data->result_type == E_GDBUS_TYPE_BOOLEAN, FALSE);
*out_boolean = op_data->result.out_boolean;
return TRUE;
}
/* caller takes ownership and responsibility for freeing the out parameter */
gboolean
e_gdbus_proxy_finish_call_string (EGdbusAsyncOpKeeper *proxy,
GAsyncResult *result,
gchar **out_string,
GError **error,
gpointer source_tag)
{
AsyncOpData *op_data;
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), source_tag), FALSE);
g_return_val_if_fail (out_string != NULL, FALSE);
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
return FALSE;
op_data = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
g_return_val_if_fail (op_data != NULL, FALSE);
g_return_val_if_fail (op_data->result_type == E_GDBUS_TYPE_STRING, FALSE);
*out_string = op_data->result.out_string;
op_data->result.out_string = NULL;
return TRUE;
}
/* caller takes ownership and responsibility for freeing the out parameter */
gboolean
e_gdbus_proxy_finish_call_strv (EGdbusAsyncOpKeeper *proxy,
GAsyncResult *result,
gchar ***out_strv,
GError **error,
gpointer source_tag)
{
AsyncOpData *op_data;
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), source_tag), FALSE);
g_return_val_if_fail (out_strv != NULL, FALSE);
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
return FALSE;
op_data = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
g_return_val_if_fail (op_data != NULL, FALSE);
g_return_val_if_fail (op_data->result_type == E_GDBUS_TYPE_STRV, FALSE);
*out_strv = op_data->result.out_strv;
op_data->result.out_strv = NULL;
return TRUE;
}
gboolean
e_gdbus_proxy_finish_call_uint (EGdbusAsyncOpKeeper *proxy,
GAsyncResult *result,
guint *out_uint,
GError **error,
gpointer source_tag)
{
AsyncOpData *op_data;
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), source_tag), FALSE);
g_return_val_if_fail (out_uint != NULL, FALSE);
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
return FALSE;
op_data = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
g_return_val_if_fail (op_data != NULL, FALSE);
g_return_val_if_fail (op_data->result_type == E_GDBUS_TYPE_UINT, FALSE);
*out_uint = op_data->result.out_uint;
return TRUE;
}
typedef struct _SyncOpData
{
EFlag *flag;
GError **error;
guint out_type; /* one of E_GDBUS_TYPE_... except of E_GDBUS_TYPE_IS_ASYNC */
union {
gboolean *out_boolean;
gchar **out_string;
gchar ***out_strv;
guint *out_uint;
} out_arg;
union {
EGdbusCallFinishVoid finish_void;
EGdbusCallFinishBoolean finish_boolean;
EGdbusCallFinishString finish_string;
EGdbusCallFinishStrv finish_strv;
EGdbusCallFinishUint finish_uint;
} finish_func;
gboolean finish_result;
} SyncOpData;
#define SYNC_DATA_HASH_KEY "EGdbusTemplates-SyncOp-Hash"
static GMutex sync_data_hash_mutex;
static void
e_gdbus_proxy_sync_ready_cb (GObject *proxy,
GAsyncResult *result,
gpointer user_data)
{
gint sync_opid = GPOINTER_TO_INT (user_data);
SyncOpData *sync_data = NULL;
GHashTable *sync_data_hash;
g_mutex_lock (&sync_data_hash_mutex);
sync_data_hash = g_object_get_data (proxy, SYNC_DATA_HASH_KEY);
if (sync_data_hash)
sync_data = g_hash_table_lookup (sync_data_hash, GINT_TO_POINTER (sync_opid));
g_mutex_unlock (&sync_data_hash_mutex);
if (!sync_data) {
/* already finished operation; it can happen when the operation is cancelled,
* but the result is already waiting in an idle queue.
*/
return;
}
g_return_if_fail (sync_data->flag != NULL);
switch (sync_data->out_type) {
case E_GDBUS_TYPE_VOID:
g_return_if_fail (sync_data->finish_func.finish_void != NULL);
sync_data->finish_result = sync_data->finish_func.finish_void (G_DBUS_PROXY (proxy), result, sync_data->error);
break;
case E_GDBUS_TYPE_BOOLEAN:
g_return_if_fail (sync_data->finish_func.finish_boolean != NULL);
sync_data->finish_result = sync_data->finish_func.finish_boolean (G_DBUS_PROXY (proxy), result, sync_data->out_arg.out_boolean, sync_data->error);
break;
case E_GDBUS_TYPE_STRING:
g_return_if_fail (sync_data->finish_func.finish_string != NULL);
sync_data->finish_result = sync_data->finish_func.finish_string (G_DBUS_PROXY (proxy), result, sync_data->out_arg.out_string, sync_data->error);
break;
case E_GDBUS_TYPE_STRV:
g_return_if_fail (sync_data->finish_func.finish_strv != NULL);
sync_data->finish_result = sync_data->finish_func.finish_strv (G_DBUS_PROXY (proxy), result, sync_data->out_arg.out_strv, sync_data->error);
break;
case E_GDBUS_TYPE_UINT:
g_return_if_fail (sync_data->finish_func.finish_uint != NULL);
sync_data->finish_result = sync_data->finish_func.finish_uint (G_DBUS_PROXY (proxy), result, sync_data->out_arg.out_uint, sync_data->error);
break;
default:
g_warning ("%s: Unknown 'out' E_GDBUS_TYPE %x", G_STRFUNC, sync_data->out_type);
sync_data->finish_result = FALSE;
}
e_flag_set (sync_data->flag);
}
static gboolean
e_gdbus_proxy_call_sync (GDBusProxy *proxy,
GCancellable *cancellable,
GError **error,
gpointer start_func,
gpointer finish_func,
guint in_type,
gconstpointer in_value,
guint out_type,
gpointer out_value)
{
static volatile gint sync_op_counter = 0;
gint sync_opid;
gpointer sync_opid_ident;
SyncOpData sync_data = { 0 };
GHashTable *sync_data_hash;
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
g_object_ref (proxy);
switch (out_type) {
case E_GDBUS_TYPE_VOID:
sync_data.finish_func.finish_void = finish_func;
break;
case E_GDBUS_TYPE_BOOLEAN:
sync_data.out_arg.out_boolean = out_value;
sync_data.finish_func.finish_boolean = finish_func;
break;
case E_GDBUS_TYPE_STRING:
sync_data.out_arg.out_string = out_value;
sync_data.finish_func.finish_string = finish_func;
break;
case E_GDBUS_TYPE_STRV:
sync_data.out_arg.out_strv = out_value;
sync_data.finish_func.finish_strv = finish_func;
break;
case E_GDBUS_TYPE_UINT:
sync_data.out_arg.out_uint = out_value;
sync_data.finish_func.finish_uint = finish_func;
break;
default:
g_warning ("%s: Unknown 'out' E_GDBUS_TYPE %x", G_STRFUNC, out_type);
g_object_unref (proxy);
return FALSE;
}
sync_data.flag = e_flag_new ();
sync_data.error = error;
sync_data.out_type = out_type;
sync_opid = g_atomic_int_add (&sync_op_counter, 1);
g_mutex_lock (&sync_data_hash_mutex);
sync_data_hash = g_object_get_data (G_OBJECT (proxy), SYNC_DATA_HASH_KEY);
if (!sync_data_hash) {
sync_data_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
g_object_set_data_full (
G_OBJECT (proxy), SYNC_DATA_HASH_KEY, sync_data_hash,
(GDestroyNotify) g_hash_table_destroy);
}
sync_opid_ident = GINT_TO_POINTER (sync_opid);
g_hash_table_insert (sync_data_hash, sync_opid_ident, &sync_data);
g_mutex_unlock (&sync_data_hash_mutex);
switch (in_type) {
case E_GDBUS_TYPE_VOID: {
EGdbusCallStartVoid start = start_func;
start (proxy, cancellable, e_gdbus_proxy_sync_ready_cb, GINT_TO_POINTER (sync_opid));
} break;
case E_GDBUS_TYPE_BOOLEAN: {
EGdbusCallStartBoolean start = start_func;
start (proxy, * ((gboolean *) in_value), cancellable, e_gdbus_proxy_sync_ready_cb, GINT_TO_POINTER (sync_opid));
} break;
case E_GDBUS_TYPE_STRING: {
EGdbusCallStartString start = start_func;
start (proxy, (const gchar *) in_value, cancellable, e_gdbus_proxy_sync_ready_cb, GINT_TO_POINTER (sync_opid));
} break;
case E_GDBUS_TYPE_STRV: {
EGdbusCallStartStrv start = start_func;
start (proxy, (const gchar * const *) in_value, cancellable, e_gdbus_proxy_sync_ready_cb, GINT_TO_POINTER (sync_opid));
} break;
case E_GDBUS_TYPE_UINT: {
EGdbusCallStartUint start = start_func;
start (proxy, * ((guint *) in_value), cancellable, e_gdbus_proxy_sync_ready_cb, GINT_TO_POINTER (sync_opid));
} break;
default:
g_warning ("%s: Unknown 'in' E_GDBUS_TYPE %x", G_STRFUNC, in_type);
e_flag_free (sync_data.flag);
g_mutex_lock (&sync_data_hash_mutex);
g_hash_table_remove (sync_data_hash, sync_opid_ident);
g_mutex_unlock (&sync_data_hash_mutex);
g_object_unref (proxy);
return FALSE;
}
/* check if called from the main thread */
if ((main_thread && main_thread == g_thread_self ()) ||
(!main_thread && (g_main_context_is_owner (g_main_context_default ())
|| g_main_context_default () == g_main_context_get_thread_default ()
|| !g_main_context_get_thread_default ()))) {
/* the call to e_gdbus_templates_init_main_thread() wasn't done, but no problem,
* check if the call was done in the main thread with main loop running,
* and if so, then remember it
*/
if (!main_thread && g_main_context_is_owner (g_main_context_default ()))
e_gdbus_templates_init_main_thread ();
/* Might not be the best thing here, but as the async operation
* is divided into two-step process, invoking the method and
* waiting for its "done" signal, then if the sync method is called
* from the main thread, then there is probably no other option.
*/
while (!e_flag_is_set (sync_data.flag)) {
g_usleep (1000);
g_main_context_iteration (NULL, FALSE);
}
} else {
/* is called in a dedicated thread */
e_flag_wait (sync_data.flag);
}
g_mutex_lock (&sync_data_hash_mutex);
g_hash_table_remove (sync_data_hash, sync_opid_ident);
g_mutex_unlock (&sync_data_hash_mutex);
e_flag_free (sync_data.flag);
g_object_unref (proxy);
return sync_data.finish_result;
}
gboolean
e_gdbus_proxy_call_sync_void__void (GDBusProxy *proxy,
GCancellable *cancellable,
GError **error,
EGdbusCallStartVoid start_func,
EGdbusCallFinishVoid finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_VOID, NULL, E_GDBUS_TYPE_VOID, NULL);
}
/**
* e_gdbus_proxy_call_sync_void__boolean:
* @proxy:
* @out_boolean:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_call_sync_void__boolean (GDBusProxy *proxy,
gboolean *out_boolean,
GCancellable *cancellable,
GError **error,
EGdbusCallStartVoid start_func,
EGdbusCallFinishBoolean finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
g_return_val_if_fail (out_boolean != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_VOID, NULL, E_GDBUS_TYPE_BOOLEAN, out_boolean);
}
/**
* e_gdbus_proxy_call_sync_void__string:
* @proxy:
* @out_string:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_call_sync_void__string (GDBusProxy *proxy,
gchar **out_string,
GCancellable *cancellable,
GError **error,
EGdbusCallStartVoid start_func,
EGdbusCallFinishString finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
g_return_val_if_fail (out_string != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_VOID, NULL, E_GDBUS_TYPE_STRING, out_string);
}
/**
* e_gdbus_proxy_call_sync_void__strv:
* @proxy:
* @out_strv:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_call_sync_void__strv (GDBusProxy *proxy,
gchar ***out_strv,
GCancellable *cancellable,
GError **error,
EGdbusCallStartVoid start_func,
EGdbusCallFinishStrv finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
g_return_val_if_fail (out_strv != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_VOID, NULL, E_GDBUS_TYPE_STRV, out_strv);
}
/**
* e_gdbus_proxy_call_sync_void__uint:
* @proxy:
* @out_uint:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_call_sync_void__uint (GDBusProxy *proxy,
guint *out_uint,
GCancellable *cancellable,
GError **error,
EGdbusCallStartVoid start_func,
EGdbusCallFinishUint finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
g_return_val_if_fail (out_uint != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_VOID, NULL, E_GDBUS_TYPE_UINT, out_uint);
}
gboolean
e_gdbus_proxy_call_sync_boolean__void (GDBusProxy *proxy,
gboolean in_boolean,
GCancellable *cancellable,
GError **error,
EGdbusCallStartBoolean start_func,
EGdbusCallFinishVoid finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_BOOLEAN, &in_boolean, E_GDBUS_TYPE_VOID, NULL);
}
/**
* e_gdbus_proxy_call_sync_string__void:
* @proxy:
* @in_string:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_call_sync_string__void (GDBusProxy *proxy,
const gchar *in_string,
GCancellable *cancellable,
GError **error,
EGdbusCallStartString start_func,
EGdbusCallFinishVoid finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
g_return_val_if_fail (in_string != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_STRING, in_string, E_GDBUS_TYPE_VOID, NULL);
}
gboolean
e_gdbus_proxy_call_sync_strv__void (GDBusProxy *proxy,
const gchar * const *in_strv,
GCancellable *cancellable,
GError **error,
EGdbusCallStartStrv start_func,
EGdbusCallFinishVoid finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
g_return_val_if_fail (in_strv != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_STRV, in_strv, E_GDBUS_TYPE_VOID, NULL);
}
/**
* e_gdbus_proxy_call_sync_uint__void:
* @proxy:
* @in_uint:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_call_sync_uint__void (GDBusProxy *proxy,
guint in_uint,
GCancellable *cancellable,
GError **error,
EGdbusCallStartUint start_func,
EGdbusCallFinishVoid finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_UINT, &in_uint, E_GDBUS_TYPE_VOID, NULL);
}
gboolean
e_gdbus_proxy_call_sync_string__string (GDBusProxy *proxy,
const gchar *in_string,
gchar **out_string,
GCancellable *cancellable,
GError **error,
EGdbusCallStartString start_func,
EGdbusCallFinishString finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
g_return_val_if_fail (in_string != NULL, FALSE);
g_return_val_if_fail (out_string != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_STRING, in_string, E_GDBUS_TYPE_STRING, out_string);
}
/**
* e_gdbus_proxy_call_sync_string__strv:
* @proxy:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_call_sync_string__strv (GDBusProxy *proxy,
const gchar *in_string,
gchar ***out_strv,
GCancellable *cancellable,
GError **error,
EGdbusCallStartString start_func,
EGdbusCallFinishStrv finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
g_return_val_if_fail (in_string != NULL, FALSE);
g_return_val_if_fail (out_strv != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_STRING, in_string, E_GDBUS_TYPE_STRV, out_strv);
}
gboolean
e_gdbus_proxy_call_sync_strv__string (GDBusProxy *proxy,
const gchar * const *in_strv,
gchar **out_string,
GCancellable *cancellable,
GError **error,
EGdbusCallStartStrv start_func,
EGdbusCallFinishString finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
g_return_val_if_fail (in_strv != NULL, FALSE);
g_return_val_if_fail (out_string != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_STRV, in_strv, E_GDBUS_TYPE_STRING, out_string);
}
/**
* e_gdbus_proxy_call_sync_strv__strv:
* @proxy:
* @in_strv:
* @out_strv:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_call_sync_strv__strv (GDBusProxy *proxy,
const gchar * const *in_strv,
gchar ***out_strv,
GCancellable *cancellable,
GError **error,
EGdbusCallStartStrv start_func,
EGdbusCallFinishStrv finish_func)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (start_func != NULL, FALSE);
g_return_val_if_fail (finish_func != NULL, FALSE);
g_return_val_if_fail (in_strv != NULL, FALSE);
g_return_val_if_fail (out_strv != NULL, FALSE);
return e_gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_STRV, in_strv, E_GDBUS_TYPE_STRV, out_strv);
}
static void
proxy_method_call (const gchar *method_name,
guint param_type,
gconstpointer param_value,
GDBusProxy *proxy,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GVariant *params = NULL;
GVariant *item;
GVariantBuilder *builder = NULL;
g_return_if_fail (method_name != NULL);
g_return_if_fail (proxy != NULL);
g_return_if_fail (G_IS_DBUS_PROXY (proxy));
if (param_type != E_GDBUS_TYPE_VOID)
g_return_if_fail (param_value != NULL);
switch (param_type) {
case E_GDBUS_TYPE_VOID:
break;
case E_GDBUS_TYPE_BOOLEAN:
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
item = g_variant_new_boolean (* ((const gboolean *) param_value));
g_variant_builder_add_value (builder, item);
break;
case E_GDBUS_TYPE_STRING:
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
item = g_variant_new_string ((const gchar *) param_value);
g_variant_builder_add_value (builder, item);
break;
case E_GDBUS_TYPE_STRV:
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
item = g_variant_new_strv ((const gchar * const *) param_value, -1);
g_variant_builder_add_value (builder, item);
break;
case E_GDBUS_TYPE_UINT:
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
item = g_variant_new_uint32 (* ((const guint *) param_value));
g_variant_builder_add_value (builder, item);
break;
default:
g_warning ("%s: Unknown 'param' E_GDBUS_TYPE %x", G_STRFUNC, param_type);
return;
}
if (builder != NULL) {
params = g_variant_builder_end (builder);
g_variant_builder_unref (builder);
}
g_dbus_proxy_call (G_DBUS_PROXY (proxy), method_name, params, G_DBUS_CALL_FLAGS_NONE, e_data_server_util_get_dbus_call_timeout (), cancellable, callback, user_data);
}
void
e_gdbus_proxy_method_call_void (const gchar *method_name,
GDBusProxy *proxy,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
proxy_method_call (method_name, E_GDBUS_TYPE_VOID, NULL, proxy, cancellable, callback, user_data);
}
void
e_gdbus_proxy_method_call_boolean (const gchar *method_name,
GDBusProxy *proxy,
gboolean in_boolean,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
proxy_method_call (method_name, E_GDBUS_TYPE_BOOLEAN, &in_boolean, proxy, cancellable, callback, user_data);
}
void
e_gdbus_proxy_method_call_string (const gchar *method_name,
GDBusProxy *proxy,
const gchar *in_string,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
proxy_method_call (method_name, E_GDBUS_TYPE_STRING, in_string, proxy, cancellable, callback, user_data);
}
void
e_gdbus_proxy_method_call_strv (const gchar *method_name,
GDBusProxy *proxy,
const gchar * const *in_strv,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
proxy_method_call (method_name, E_GDBUS_TYPE_STRV, in_strv, proxy, cancellable, callback, user_data);
}
void
e_gdbus_proxy_method_call_uint (const gchar *method_name,
GDBusProxy *proxy,
guint in_uint,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
proxy_method_call (method_name, E_GDBUS_TYPE_VOID, &in_uint, proxy, cancellable, callback, user_data);
}
static gboolean
process_result (const gchar *caller_func_name,
guint out_type,
gpointer out_value,
GVariant *_result)
{
if (out_type != E_GDBUS_TYPE_VOID)
g_return_val_if_fail (out_value != NULL, FALSE);
if (_result == NULL)
return FALSE;
switch (out_type) {
case E_GDBUS_TYPE_VOID:
break;
case E_GDBUS_TYPE_BOOLEAN:
g_variant_get (_result, "(b)", (gboolean *) out_value);
break;
case E_GDBUS_TYPE_STRING:
g_variant_get (_result, "(s)", (gchar **) out_value);
break;
case E_GDBUS_TYPE_STRV:
g_variant_get (_result, "(^as)", (gchar ***) out_value);
break;
case E_GDBUS_TYPE_UINT:
g_variant_get (_result, "(u)", (guint *) out_value);
break;
default:
g_warning ("%s: Unknown 'out' E_GDBUS_TYPE %x", caller_func_name ? caller_func_name : G_STRFUNC, out_type);
break;
}
g_variant_unref (_result);
return TRUE;
}
static gboolean
proxy_method_call_finish (guint out_type,
gpointer out_param,
GDBusProxy *proxy,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), FALSE);
if (out_type != E_GDBUS_TYPE_VOID)
g_return_val_if_fail (out_param != NULL, FALSE);
return process_result (G_STRFUNC, out_type, out_param, g_dbus_proxy_call_finish (proxy, result, error));
}
gboolean
e_gdbus_proxy_method_call_finish_void (GDBusProxy *proxy,
GAsyncResult *result,
GError **error)
{
return proxy_method_call_finish (E_GDBUS_TYPE_VOID, NULL, proxy, result, error);
}
gboolean
e_gdbus_proxy_method_call_finish_boolean (GDBusProxy *proxy,
GAsyncResult *result,
gboolean *out_boolean,
GError **error)
{
return proxy_method_call_finish (E_GDBUS_TYPE_BOOLEAN, out_boolean, proxy, result, error);
}
gboolean
e_gdbus_proxy_method_call_finish_string (GDBusProxy *proxy,
GAsyncResult *result,
gchar **out_string,
GError **error)
{
return proxy_method_call_finish (E_GDBUS_TYPE_STRING, out_string, proxy, result, error);
}
gboolean
e_gdbus_proxy_method_call_finish_strv (GDBusProxy *proxy,
GAsyncResult *result,
gchar ***out_strv,
GError **error)
{
return proxy_method_call_finish (E_GDBUS_TYPE_STRV, out_strv, proxy, result, error);
}
gboolean
e_gdbus_proxy_method_call_finish_uint (GDBusProxy *proxy,
GAsyncResult *result,
guint *out_uint,
GError **error)
{
return proxy_method_call_finish (E_GDBUS_TYPE_UINT, out_uint, proxy, result, error);
}
static gboolean
proxy_method_call_sync (const gchar *method_name,
guint in_type,
gconstpointer in_value,
guint out_type,
gpointer out_value,
GDBusProxy *proxy,
GCancellable *cancellable,
GError **error)
{
GVariant *params = NULL;
GVariant *item;
GVariantBuilder *builder = NULL;
g_return_val_if_fail (method_name != NULL, FALSE);
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), FALSE);
if (in_type != E_GDBUS_TYPE_VOID)
g_return_val_if_fail (in_value != NULL, FALSE);
if (out_type != E_GDBUS_TYPE_VOID)
g_return_val_if_fail (out_value != NULL, FALSE);
switch (in_type) {
case E_GDBUS_TYPE_VOID:
break;
case E_GDBUS_TYPE_BOOLEAN:
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
item = g_variant_new_boolean (* ((const gboolean *) in_value));
g_variant_builder_add_value (builder, item);
break;
case E_GDBUS_TYPE_STRING:
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
item = g_variant_new_string ((const gchar *) in_value);
g_variant_builder_add_value (builder, item);
break;
case E_GDBUS_TYPE_STRV:
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
item = g_variant_new_strv ((const gchar * const *) in_value, -1);
g_variant_builder_add_value (builder, item);
break;
case E_GDBUS_TYPE_UINT:
builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
item = g_variant_new_uint32 (* ((const guint *) in_value));
g_variant_builder_add_value (builder, item);
break;
default:
g_warning ("%s: Unknown 'in' E_GDBUS_TYPE %x", G_STRFUNC, in_type);
return FALSE;
}
if (builder != NULL) {
params = g_variant_builder_end (builder);
g_variant_builder_unref (builder);
}
return process_result (G_STRFUNC, out_type, out_value, g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), method_name, params, G_DBUS_CALL_FLAGS_NONE, e_data_server_util_get_dbus_call_timeout (), cancellable, error));
}
/**
* e_gdbus_proxy_call_sync_void__void:
* @proxy:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_method_call_sync_void__void (const gchar *method_name,
GDBusProxy *proxy,
GCancellable *cancellable,
GError **error)
{
return proxy_method_call_sync (method_name, E_GDBUS_TYPE_VOID, NULL, E_GDBUS_TYPE_VOID, NULL, proxy, cancellable, error);
}
/**
* e_gdbus_proxy_call_sync_boolean__void:
* @proxy:
* @in_boolean:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_method_call_sync_boolean__void (const gchar *method_name,
GDBusProxy *proxy,
gboolean in_boolean,
GCancellable *cancellable,
GError **error)
{
return proxy_method_call_sync (method_name, E_GDBUS_TYPE_BOOLEAN, &in_boolean, E_GDBUS_TYPE_VOID, NULL, proxy, cancellable, error);
}
gboolean
e_gdbus_proxy_method_call_sync_string__void (const gchar *method_name,
GDBusProxy *proxy,
const gchar *in_string,
GCancellable *cancellable,
GError **error)
{
return proxy_method_call_sync (method_name, E_GDBUS_TYPE_STRING, in_string, E_GDBUS_TYPE_VOID, NULL, proxy, cancellable, error);
}
/**
* e_gdbus_proxy_call_sync_strv__void:
* @proxy:
* @in_strv:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_method_call_sync_strv__void (const gchar *method_name,
GDBusProxy *proxy,
const gchar * const *in_strv,
GCancellable *cancellable,
GError **error)
{
return proxy_method_call_sync (method_name, E_GDBUS_TYPE_STRV, in_strv, E_GDBUS_TYPE_VOID, NULL, proxy, cancellable, error);
}
gboolean
e_gdbus_proxy_method_call_sync_uint__void (const gchar *method_name,
GDBusProxy *proxy,
guint in_uint,
GCancellable *cancellable,
GError **error)
{
return proxy_method_call_sync (method_name, E_GDBUS_TYPE_UINT, &in_uint, E_GDBUS_TYPE_VOID, NULL, proxy, cancellable, error);
}
/**
* e_gdbus_proxy_call_sync_string__string:
* @proxy:
* @in_string:
* @out_string:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_method_call_sync_string__string (const gchar *method_name,
GDBusProxy *proxy,
const gchar *in_string,
gchar **out_string,
GCancellable *cancellable,
GError **error)
{
return proxy_method_call_sync (method_name, E_GDBUS_TYPE_STRING, in_string, E_GDBUS_TYPE_STRING, out_string, proxy, cancellable, error);
}
/**
* e_gdbus_proxy_call_sync_strv__string:
* @proxy:
* @in_strv:
* @out_string:
* @cancellable: (allow-none):
* @error:
* @start_func: (scope call):
* @finish_func: (scope call):
*
* Returns:
*/
gboolean
e_gdbus_proxy_method_call_sync_strv__string (const gchar *method_name,
GDBusProxy *proxy,
const gchar * const *in_strv,
gchar **out_string,
GCancellable *cancellable,
GError **error)
{
return proxy_method_call_sync (method_name, E_GDBUS_TYPE_STRV, in_strv, E_GDBUS_TYPE_STRING, out_string, proxy, cancellable, error);
}
/**
* e_gdbus_templates_encode_error:
* @in_error: (allow-none):
*
* Returns: (transfer full): a %NULL-terminated array of strings; free with
* g_strfreev()
*/
gchar **
e_gdbus_templates_encode_error (const GError *in_error)
{
gchar **strv;
strv = g_new0 (gchar *, 3);
if (!in_error) {
strv[0] = g_strdup ("");
strv[1] = g_strdup ("");
} else {
gchar *dbus_error_name = g_dbus_error_encode_gerror (in_error);
strv[0] = e_util_utf8_make_valid (dbus_error_name ? dbus_error_name : "");
strv[1] = e_util_utf8_make_valid (in_error->message);
g_free (dbus_error_name);
}
return strv;
}
/* free *out_error with g_error_free(), if not NULL */
gboolean
e_gdbus_templates_decode_error (const gchar * const *in_strv,
GError **out_error)
{
const gchar *error_name, *error_message;
g_return_val_if_fail (out_error != NULL, FALSE);
*out_error = NULL;
g_return_val_if_fail (in_strv != NULL, FALSE);
g_return_val_if_fail (in_strv[0] != NULL, FALSE);
g_return_val_if_fail (in_strv[1] != NULL, FALSE);
g_return_val_if_fail (in_strv[2] == NULL, FALSE);
error_name = in_strv[0];
error_message = in_strv[1];
if (error_name && *error_name && error_message)
*out_error = g_dbus_error_new_for_dbus_error (error_name, error_message);
return TRUE;
}
/**
* e_gdbus_templates_encode_two_strings:
* @in_str1: (allow-none):
* @in_str2: (allow-none):
*
* Returns: (transfer full): a %NULL-terminated array of strings; free with
* g_strfreev()
*/
gchar **
e_gdbus_templates_encode_two_strings (const gchar *in_str1,
const gchar *in_str2)
{
gchar **strv;
strv = g_new0 (gchar *, 3);
strv[0] = e_util_utf8_make_valid (in_str1 ? in_str1 : "");
strv[1] = e_util_utf8_make_valid (in_str2 ? in_str2 : "");
strv[2] = NULL;
return strv;
}
/* free *out_str1 and *out_str2 with g_free() */
gboolean
e_gdbus_templates_decode_two_strings (const gchar * const *in_strv,
gchar **out_str1,
gchar **out_str2)
{
g_return_val_if_fail (in_strv != NULL, FALSE);
g_return_val_if_fail (in_strv[0] != NULL, FALSE);
g_return_val_if_fail (in_strv[1] != NULL, FALSE);
g_return_val_if_fail (in_strv[2] == NULL, FALSE);
g_return_val_if_fail (out_str1 != NULL, FALSE);
g_return_val_if_fail (out_str2 != NULL, FALSE);
*out_str1 = g_strdup (in_strv[0]);
*out_str2 = g_strdup (in_strv[1]);
return TRUE;
}