Commented out export of missing CRML source file to avoid build error.
There are no known side effects of this file being missing, so this seems a reasonable way to avoid the build error.
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-gobject.c Exporting a GObject remotely
*
* Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
* Copyright (C) 2005 Nokia
* Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __SYMBIAN32__
#include <config.h>
#else
#include "config.h"
#endif //__SYMBIAN32__
#include <gobject/gvaluecollector.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include "dbus-gtest.h"
#include "dbus-gutils.h"
#include "dbus-gobject.h"
#include "dbus-gsignature.h"
#include "dbus-gvalue.h"
#include "dbus-gmarshal.h"
#include "dbus-gvalue-utils.h"
#include <string.h>
#ifdef __SYMBIAN32__
#include "libdbus_glib_wsd_solution.h"
#endif
typedef struct
{
char *default_iface;
GType code_enum;
} DBusGErrorInfo;
#if EMULATOR
GET_STATIC_VAR_FROM_TLS(marshal_table,dbus_gobject,GHashTable *)
#define marshal_table (*GET_DBUS_WSD_VAR_NAME(marshal_table,dbus_gobject,s)())
GET_STATIC_VAR_FROM_TLS(error_metadata,dbus_gobject,GData *)
#define error_metadata (*GET_DBUS_WSD_VAR_NAME(error_metadata,dbus_gobject,s)())
GET_STATIC_VAR_FROM_TLS(globals_lock,dbus_gobject,GStaticRWLock )
#define globals_lock (*GET_DBUS_WSD_VAR_NAME(globals_lock,dbus_gobject,s)())
#else
static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
static GHashTable *marshal_table = NULL;
static GData *error_metadata = NULL;
#endif
static char*
uscore_to_wincaps (const char *uscore)
{
const char *p;
GString *str;
gboolean last_was_uscore;
last_was_uscore = TRUE;
str = g_string_new (NULL);
p = uscore;
while (p && *p)
{
if (*p == '-' || *p == '_')
{
last_was_uscore = TRUE;
}
else
{
if (last_was_uscore)
{
g_string_append_c (str, g_ascii_toupper (*p));
last_was_uscore = FALSE;
}
else
g_string_append_c (str, *p);
}
++p;
}
return g_string_free (str, FALSE);
}
static const char *
string_table_next (const char *table)
{
return (table + (strlen (table) + 1));
}
static const char *
string_table_lookup (const char *table, int index)
{
const char *ret;
ret = table;
while (index--)
ret = string_table_next (ret);
return ret;
}
static const char *
get_method_data (const DBusGObjectInfo *object,
const DBusGMethodInfo *method)
{
return object->data + method->data_offset;
}
static char *
object_error_domain_prefix_from_object_info (const DBusGObjectInfo *info)
{
/* FIXME */
return NULL;
}
static char *
object_error_code_from_object_info (const DBusGObjectInfo *info, GQuark domain, gint code)
{
/* FIXME */
return NULL;
}
static const char *
method_interface_from_object_info (const DBusGObjectInfo *object,
const DBusGMethodInfo *method)
{
return string_table_lookup (get_method_data (object, method), 0);
}
static const char *
method_name_from_object_info (const DBusGObjectInfo *object,
const DBusGMethodInfo *method)
{
return string_table_lookup (get_method_data (object, method), 1);
}
static const char *
method_arg_info_from_object_info (const DBusGObjectInfo *object,
const DBusGMethodInfo *method)
{
return string_table_lookup (get_method_data (object, method), 3);/*RB was 2*/
}
typedef enum
{
RETVAL_NONE,
RETVAL_NOERROR,
RETVAL_ERROR
} RetvalType;
static const char *
arg_iterate (const char *data,
const char **name,
gboolean *in,
gboolean *constval,
RetvalType *retval,
const char **type)
{
gboolean inarg;
if (name)
*name = data;
data = string_table_next (data);
switch (*data)
{
case 'I':
inarg = TRUE;
break;
case 'O':
inarg = FALSE;
break;
default:
g_warning ("invalid arg direction '%c'", *data);
inarg = FALSE;
break;
}
if (in)
*in = inarg;
if (!inarg)
{
data = string_table_next (data);
switch (*data)
{
case 'F':
if (constval)
*constval = FALSE;
break;
case 'C':
if (constval)
*constval = TRUE;
break;
default:
g_warning ("invalid arg const value '%c'", *data);
break;
}
data = string_table_next (data);
switch (*data)
{
case 'N':
if (retval)
*retval = RETVAL_NONE;
break;
case 'E':
if (retval)
*retval = RETVAL_ERROR;
break;
case 'R':
if (retval)
*retval = RETVAL_NOERROR;
break;
default:
g_warning ("invalid arg ret value '%c'", *data);
break;
}
}
else
{
if (constval)
*constval = FALSE;
if (retval)
#ifndef __SYMBIAN32__
*retval = FALSE;
#else
*retval = (RetvalType)FALSE;
#endif
}
data = string_table_next (data);
if (type)
*type = data;
return string_table_next (data);
}
static char *
method_dir_signature_from_object_info (const DBusGObjectInfo *object,
const DBusGMethodInfo *method,
gboolean in)
{
const char *arg;
GString *ret;
arg = method_arg_info_from_object_info (object, method);
ret = g_string_new (NULL);
while (*arg)
{
const char *name;
gboolean arg_in;
const char *type;
arg = arg_iterate (arg, &name, &arg_in, NULL, NULL, &type);
if (arg_in == in)
g_string_append (ret, type);
}
return g_string_free (ret, FALSE);
}
static char *
method_input_signature_from_object_info (const DBusGObjectInfo *object,
const DBusGMethodInfo *method)
{
return method_dir_signature_from_object_info (object, method, TRUE);
}
static char *
method_output_signature_from_object_info (const DBusGObjectInfo *object,
const DBusGMethodInfo *method)
{
return method_dir_signature_from_object_info (object, method, FALSE);
}
static const char *
propsig_iterate (const char *data, const char **iface, const char **name)
{
*iface = data;
data = string_table_next (data);
*name = data;
return string_table_next (data);
}
#if EMULATOR
GET_STATIC_VAR_FROM_TLS(quark,dbus_gobject,GQuark )
#define quark (*GET_DBUS_WSD_VAR_NAME(quark,dbus_gobject,s)())
#endif
static GQuark
dbus_g_object_type_dbus_metadata_quark (void)
{
#ifndef EMULATOR
static GQuark quark;
#endif
if (!quark)
quark = g_quark_from_static_string ("DBusGObjectTypeDBusMetadataQuark");
return quark;
}
static GList *
lookup_object_info (GObject *object)
{
GType *interfaces, *p;
GList *info_list = NULL;
const DBusGObjectInfo *info;
GType classtype;
interfaces = g_type_interfaces (G_TYPE_FROM_INSTANCE (object), NULL);
for (p = interfaces; *p != 0; p++)
{
info = g_type_get_qdata (*p, dbus_g_object_type_dbus_metadata_quark ());
if (info != NULL && info->format_version >= 0)
info_list = g_list_prepend (info_list, (gpointer) info);
}
g_free (interfaces);
for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
{
info = g_type_get_qdata (classtype, dbus_g_object_type_dbus_metadata_quark ());
if (info != NULL && info->format_version >= 0)
info_list = g_list_prepend (info_list, (gpointer) info);
}
/* if needed only:
return g_list_reverse (info_list);
*/
return info_list;
}
static void
gobject_unregister_function (DBusConnection *connection,
void *user_data)
{
#ifdef WINSCW
GObject *object;
object = G_OBJECT (user_data);
#endif
/* FIXME */
}
typedef struct
{
GString *xml;
GType gtype;
const DBusGObjectInfo *object_info;
} DBusGLibWriteIterfaceData;
typedef struct
{
GSList *methods;
GSList *signals;
GSList *properties;
} DBusGLibWriteInterfaceValues;
static void
write_interface (gpointer key, gpointer val, gpointer user_data)
{
const char *name;
GSList *methods;
GSList *signals;
GSList *properties;
GString *xml;
const DBusGObjectInfo *object_info;
DBusGLibWriteIterfaceData *data;
DBusGLibWriteInterfaceValues *values;
name = key;
values = val;
methods = values->methods;
signals = values->signals;
properties = values->properties;
data = user_data;
xml = data->xml;
object_info = data->object_info;
g_string_append_printf (xml, " <interface name=\"%s\">\n", name);
/* FIXME: recurse to parent types ? */
for (; methods; methods = methods->next)
{
DBusGMethodInfo *method;
const char *args;
method = methods->data;
g_string_append_printf (xml, " <method name=\"%s\">\n",
method_name_from_object_info (object_info, method));
args = method_arg_info_from_object_info (object_info, method);
while (*args)
{
const char *name;
gboolean arg_in;
const char *type;
args = arg_iterate (args, &name, &arg_in, NULL, NULL, &type);
/* FIXME - handle container types */
g_string_append_printf (xml, " <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n",
name, type, arg_in ? "in" : "out");
}
g_string_append (xml, " </method>\n");
}
g_slist_free (values->methods);
for (; signals; signals = signals->next)
{
guint id;
guint arg;
const char *signame;
GSignalQuery query;
char *s;
signame = signals->data;
s = _dbus_gutils_wincaps_to_uscore (signame);
id = g_signal_lookup (s, data->gtype);
g_assert (id != 0);
g_signal_query (id, &query);
g_assert (query.return_type == G_TYPE_NONE);
g_string_append_printf (xml, " <signal name=\"%s\">\n", signame);
for (arg = 0; arg < query.n_params; arg++)
{
char *dbus_type = _dbus_gtype_to_signature (query.param_types[arg]);
g_assert (dbus_type != NULL);
g_string_append (xml, " <arg type=\"");
g_string_append (xml, dbus_type);
g_string_append (xml, "\"/>\n");
g_free (dbus_type);
}
g_string_append (xml, " </signal>\n");
g_free (s);
}
g_slist_free (values->signals);
for (; properties; properties = properties->next)
{
const char *propname;
GParamSpec *spec;
char *dbus_type;
gboolean can_set;
gboolean can_get;
char *s;
propname = properties->data;
spec = NULL;
s = _dbus_gutils_wincaps_to_uscore (propname);
spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
g_assert (spec != NULL);
g_free (s);
dbus_type = _dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
g_assert (dbus_type != NULL);
can_set = ((spec->flags & G_PARAM_WRITABLE) != 0 &&
(spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
can_get = (spec->flags & G_PARAM_READABLE) != 0;
if (can_set || can_get)
{
g_string_append_printf (xml, " <property name=\"%s\" ", propname);
g_string_append (xml, "type=\"");
g_string_append (xml, dbus_type);
g_string_append (xml, "\" access=\"");
if (can_set && can_get)
g_string_append (xml, "readwrite");
else if (can_get)
g_string_append (xml, "read");
else
{
g_assert (can_set);
g_string_append (xml, "write");
}
g_string_append (xml, "\"/>\n");
}
g_free (dbus_type);
g_string_append (xml, " </property>\n");
}
g_slist_free (values->properties);
g_free (values);
g_string_append (xml, " </interface>\n");
}
static DBusGLibWriteInterfaceValues *
lookup_values (GHashTable *interfaces, const char *method_interface)
{
DBusGLibWriteInterfaceValues *values;
if ((values = g_hash_table_lookup (interfaces, (gpointer) method_interface)) == NULL)
{
values = g_new0 (DBusGLibWriteInterfaceValues, 1);
g_hash_table_insert (interfaces, (gpointer) method_interface, values);
}
return values;
}
static void
introspect_interfaces (GObject *object, GString *xml)
{
GList *info_list;
const GList *info_list_walk;
const DBusGObjectInfo *info;
DBusGLibWriteIterfaceData data;
int i;
GHashTable *interfaces;
DBusGLibWriteInterfaceValues *values;
const char *propsig;
info_list = lookup_object_info (object);
g_assert (info_list != NULL);
/* Gather a list of all interfaces, indexed into their methods */
for (info_list_walk = info_list; info_list_walk != NULL; info_list_walk = g_list_next (info_list_walk))
{
info = (DBusGObjectInfo *) info_list_walk->data;
interfaces = g_hash_table_new (g_str_hash, g_str_equal);
g_assert (info != NULL);
for (i = 0; i < info->n_method_infos; i++)
{
#ifdef WINSCW
const char *method_name;
const char *method_args;
#endif
const char *method_interface;
const DBusGMethodInfo *method;
method = &(info->method_infos[i]);
method_interface = method_interface_from_object_info (info, method);
#ifdef WINSCW
method_name = method_name_from_object_info (info, method);
method_args = method_arg_info_from_object_info (info, method);
#endif
values = lookup_values (interfaces, method_interface);
values->methods = g_slist_prepend (values->methods, (gpointer) method);
}
propsig = info->exported_signals;
while (*propsig)
{
const char *iface;
const char *signame;
propsig = propsig_iterate (propsig, &iface, &signame);
values = lookup_values (interfaces, iface);
values->signals = g_slist_prepend (values->signals, (gpointer) signame);
}
propsig = info->exported_properties;
while (*propsig)
{
const char *iface;
const char *propname;
propsig = propsig_iterate (propsig, &iface, &propname);
values = lookup_values (interfaces, iface);
values->properties = g_slist_prepend (values->properties, (gpointer) propname);
}
memset (&data, 0, sizeof (data));
data.xml = xml;
data.gtype = G_TYPE_FROM_INSTANCE (object);
data.object_info = info;
g_hash_table_foreach (interfaces, write_interface, &data);
g_hash_table_destroy (interfaces);
}
g_list_free (info_list);
}
static DBusHandlerResult
handle_introspect (DBusConnection *connection,
DBusMessage *message,
GObject *object)
{
GString *xml;
unsigned int i;
DBusMessage *ret;
char **children;
if (!dbus_connection_list_registered (connection,
dbus_message_get_path (message),
&children))
g_error ("Out of memory");
xml = g_string_new (NULL);
g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
g_string_append (xml, "<node>\n");
/* We are introspectable, though I guess that was pretty obvious */
g_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE);
g_string_append (xml, " <method name=\"Introspect\">\n");
g_string_append_printf (xml, " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
g_string_append (xml, " </method>\n");
g_string_append (xml, " </interface>\n");
/* We support get/set properties */
g_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_PROPERTIES);
g_string_append (xml, " <method name=\"Get\">\n");
g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
g_string_append_printf (xml, " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
g_string_append_printf (xml, " <arg name=\"value\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
g_string_append (xml, " </method>\n");
g_string_append (xml, " <method name=\"Set\">\n");
g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
g_string_append_printf (xml, " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
g_string_append_printf (xml, " <arg name=\"value\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
g_string_append (xml, " </method>\n");
g_string_append (xml, " </interface>\n");
introspect_interfaces (object, xml);
/* Append child nodes */
for (i = 0; children[i]; i++)
g_string_append_printf (xml, " <node name=\"%s\"/>\n",
children[i]);
/* Close the XML, and send it to the requesting app */
g_string_append (xml, "</node>\n");
ret = dbus_message_new_method_return (message);
if (ret == NULL)
g_error ("Out of memory");
dbus_message_append_args (ret,
DBUS_TYPE_STRING, &xml->str,
DBUS_TYPE_INVALID);
dbus_connection_send (connection, ret, NULL);
dbus_message_unref (ret);
g_string_free (xml, TRUE);
dbus_free_string_array (children);
return DBUS_HANDLER_RESULT_HANDLED;
}
static DBusMessage*
set_object_property (DBusConnection *connection,
DBusMessage *message,
DBusMessageIter *iter,
GObject *object,
GParamSpec *pspec)
{
GValue value = { 0, };
DBusMessage *ret;
DBusMessageIter sub;
DBusGValueMarshalCtx context;
dbus_message_iter_recurse (iter, &sub);
context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
context.proxy = NULL;
g_value_init (&value, pspec->value_type);
if (_dbus_gvalue_demarshal (&context, &sub, &value, NULL))
{
g_object_set_property (object,
pspec->name,
&value);
g_value_unset (&value);
ret = dbus_message_new_method_return (message);
if (ret == NULL)
g_error ("out of memory");
}
else
{
ret = dbus_message_new_error (message,
DBUS_ERROR_INVALID_ARGS,
"Argument's D-BUS type can't be converted to a GType");
if (ret == NULL)
g_error ("out of memory");
}
return ret;
}
static DBusMessage*
get_object_property (DBusConnection *connection,
DBusMessage *message,
GObject *object,
GParamSpec *pspec)
{
GType value_gtype;
GValue value = {0, };
gchar *variant_sig;
DBusMessage *ret;
DBusMessageIter iter, subiter;
ret = dbus_message_new_method_return (message);
if (ret == NULL)
g_error ("out of memory");
g_value_init (&value, pspec->value_type);
g_object_get_property (object, pspec->name, &value);
variant_sig = _dbus_gvalue_to_signature (&value);
if (variant_sig == NULL)
{
value_gtype = G_VALUE_TYPE (&value);
g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
g_value_unset (&value);
return ret;
}
dbus_message_iter_init_append (ret, &iter);
if (!dbus_message_iter_open_container (&iter,
DBUS_TYPE_VARIANT,
variant_sig,
&subiter))
{
g_free (variant_sig);
g_value_unset (&value);
return ret;
}
if (!_dbus_gvalue_marshal (&subiter, &value))
{
dbus_message_unref (ret);
ret = dbus_message_new_error (message,
DBUS_ERROR_UNKNOWN_METHOD,
"Can't convert GType of object property to a D-BUS type");
}
dbus_message_iter_close_container (&iter, &subiter);
g_value_unset (&value);
g_free (variant_sig);
return ret;
}
static gboolean
lookup_object_and_method (GObject *object,
DBusMessage *message,
const DBusGObjectInfo **object_ret,
const DBusGMethodInfo **method_ret)
{
const char *interface;
const char *member;
const char *signature;
GList *info_list;
const GList *info_list_walk;
const DBusGObjectInfo *info;
int i;
interface = dbus_message_get_interface (message);
member = dbus_message_get_member (message);
signature = dbus_message_get_signature (message);
info_list = lookup_object_info (object);
for (info_list_walk = info_list; info_list_walk != NULL; info_list_walk = g_list_next (info_list_walk))
{
info = (DBusGObjectInfo *) info_list_walk->data;
*object_ret = info;
for (i = 0; i < info->n_method_infos; i++)
{
const char *expected_member;
const char *expected_interface;
char *expected_signature;
const DBusGMethodInfo *method;
method = &(info->method_infos[i]);
/* Check method interface/name and input signature */
expected_interface = method_interface_from_object_info (*object_ret, method);
expected_member = method_name_from_object_info (*object_ret, method);
expected_signature = method_input_signature_from_object_info (*object_ret, method);
if ((interface == NULL
|| strcmp (expected_interface, interface) == 0)
&& strcmp (expected_member, member) == 0
&& strcmp (expected_signature, signature) == 0)
{
g_free (expected_signature);
*method_ret = method;
g_list_free (info_list);
return TRUE;
}
g_free (expected_signature);
}
}
if (info_list)
g_list_free (info_list);
return FALSE;
}
static char *
gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info,
const char *msg_interface,
GQuark domain, gint code)
{
const char *domain_str;
const char *code_str;
GString *dbus_error_name;
domain_str = object_error_domain_prefix_from_object_info (object_info);
code_str = object_error_code_from_object_info (object_info, domain, code);
if (!domain_str || !code_str)
{
DBusGErrorInfo *info;
g_static_rw_lock_reader_lock (&globals_lock);
if (error_metadata != NULL)
info = g_datalist_id_get_data (&error_metadata, domain);
else
info = NULL;
g_static_rw_lock_reader_unlock (&globals_lock);
if (info)
{
GEnumValue *value;
GEnumClass *klass;
klass = g_type_class_ref (info->code_enum);
value = g_enum_get_value (klass, code);
g_type_class_unref (klass);
domain_str = info->default_iface;
code_str = value->value_nick;
}
}
if (!domain_str)
domain_str = msg_interface;
if (!domain_str || !code_str)
{
/* If we can't map it sensibly, make up an error name */
char *domain_from_quark;
dbus_error_name = g_string_new ("org.freedesktop.DBus.GLib.UnmappedError.");
domain_from_quark = uscore_to_wincaps (g_quark_to_string (domain));
g_string_append (dbus_error_name, domain_from_quark);
g_free (domain_from_quark);
g_string_append_printf (dbus_error_name, ".Code%d", code);
}
else
{
dbus_error_name = g_string_new (domain_str);
g_string_append_c (dbus_error_name, '.');
g_string_append (dbus_error_name, code_str);
}
return g_string_free (dbus_error_name, FALSE);
}
static DBusMessage *
gerror_to_dbus_error_message (const DBusGObjectInfo *object_info,
DBusMessage *message,
GError *error)
{
DBusMessage *reply;
if (!error)
{
char *error_msg;
error_msg = g_strdup_printf ("Method invoked for %s returned FALSE but did not set error", dbus_message_get_member (message));
reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error_msg);
g_free (error_msg);
}
else
{
if (error->domain == DBUS_GERROR)
reply = dbus_message_new_error (message,
dbus_g_error_get_name (error),
error->message);
else
{
char *error_name;
error_name = gerror_domaincode_to_dbus_error_name (object_info,
dbus_message_get_interface (message),
error->domain, error->code);
reply = dbus_message_new_error (message, error_name, error->message);
g_free (error_name);
}
}
return reply;
}
/**
* SECTION:dbus-gmethod
* @short_description: GMethod Info & Invocation
* @see_also: #DBusGMessage
* @stability: Stable
*
* These types are used to call methods on #GObject objects.
*/
/**
* The context of an asynchronous method call. See dbus_g_method_return() and
* dbus_g_method_return_error().
*/
struct _DBusGMethodInvocation {
DBusGConnection *connection; /**< The connection */
DBusGMessage *message; /**< The message which generated the method call */
const DBusGObjectInfo *object; /**< The object the method was called on */
const DBusGMethodInfo *method; /**< The method called */
};
static DBusHandlerResult
invoke_object_method (GObject *object,
const DBusGObjectInfo *object_info,
const DBusGMethodInfo *method,
DBusConnection *connection,
DBusMessage *message)
{
gboolean had_error, call_only;
GError *gerror;
GValueArray *value_array;
GValue return_value = {0,};
GClosure closure;
char *in_signature;
GArray *out_param_values = NULL;
GValueArray *out_param_gvalues = NULL;
int out_param_count;
int out_param_pos, out_param_gvalue_pos;
DBusHandlerResult result;
DBusMessage *reply;
gboolean have_retval;
gboolean retval_signals_error;
gboolean retval_is_synthetic;
gboolean retval_is_constant;
const char *arg_metadata;
gerror = NULL;
/* Determine whether or not this method should be invoked in a new
thread
*/
if (strcmp (string_table_lookup (get_method_data (object_info, method), 2), "A") == 0)
call_only = TRUE;
else
call_only = FALSE;
have_retval = FALSE;
retval_signals_error = FALSE;
retval_is_synthetic = FALSE;
retval_is_constant = FALSE;
/* This is evil. We do this to work around the fact that
* the generated glib marshallers check a flag in the closure object
* which we don't care about. We don't need/want to create
* a new closure for each invocation.
*/
memset (&closure, 0, sizeof (closure));
in_signature = method_input_signature_from_object_info (object_info, method);
/* Convert method IN parameters to GValueArray */
{
GArray *types_array;
guint n_params;
const GType *types;
DBusGValueMarshalCtx context;
GError *error = NULL;
context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
context.proxy = NULL;
types_array = _dbus_gtypes_from_arg_signature (in_signature, FALSE);
n_params = types_array->len;
types = (const GType*) types_array->data;
value_array = _dbus_gvalue_demarshal_message (&context, message, n_params, types, &error);
if (value_array == NULL)
{
g_free (in_signature);
g_array_free (types_array, TRUE);
reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error->message);
dbus_connection_send (connection, reply, NULL);
dbus_message_unref (reply);
g_error_free (error);
return DBUS_HANDLER_RESULT_HANDLED;
}
g_array_free (types_array, TRUE);
}
/* Prepend object as first argument */
g_value_array_prepend (value_array, NULL);
g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_OBJECT);
g_value_set_object (g_value_array_get_nth (value_array, 0), object);
if (call_only)
{
GValue context_value = {0,};
DBusGMethodInvocation *context;
context = g_new (DBusGMethodInvocation, 1);
context->connection = dbus_g_connection_ref (DBUS_G_CONNECTION_FROM_CONNECTION (connection));
context->message = dbus_g_message_ref (DBUS_G_MESSAGE_FROM_MESSAGE (message));
context->object = object_info;
context->method = method;
g_value_init (&context_value, G_TYPE_POINTER);
g_value_set_pointer (&context_value, context);
g_value_array_append (value_array, &context_value);
}
else
{
RetvalType retval;
gboolean arg_in;
gboolean arg_const;
const char *argsig;
arg_metadata = method_arg_info_from_object_info (object_info, method);
/* Count number of output parameters, and look for a return value */
out_param_count = 0;
while (*arg_metadata)
{
arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, &arg_const, &retval, &argsig);
if (arg_in)
continue;
if (retval != RETVAL_NONE)
{
DBusSignatureIter tmp_sigiter;
/* This is the function return value */
g_assert (!have_retval);
have_retval = TRUE;
retval_is_synthetic = FALSE;
switch (retval)
{
case RETVAL_NONE:
g_assert_not_reached ();
break;
case RETVAL_NOERROR:
retval_signals_error = FALSE;
break;
case RETVAL_ERROR:
retval_signals_error = TRUE;
break;
}
retval_is_constant = arg_const;
/* Initialize our return GValue with the specified type */
dbus_signature_iter_init (&tmp_sigiter, argsig);
g_value_init (&return_value, _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE));
}
else
{
/* It's a regular output value */
out_param_count++;
}
}
/* For compatibility, if we haven't found a return value, we assume
* the function returns a gboolean for signalling an error
* (and therefore also takes a GError). We also note that it
* is a "synthetic" return value; i.e. we aren't going to be
* sending it over the bus, it's just to signal an error.
*/
if (!have_retval)
{
have_retval = TRUE;
retval_is_synthetic = TRUE;
retval_signals_error = TRUE;
g_value_init (&return_value, G_TYPE_BOOLEAN);
}
/* Create an array to store the actual values of OUT parameters
* (other than the real function return, if any). Then, create
* a GValue boxed POINTER to each of those values, and append to
* the invocation, so the method can return the OUT parameters.
*/
out_param_values = g_array_sized_new (FALSE, TRUE, sizeof (GTypeCValue), out_param_count);
/* We have a special array of GValues for toplevel GValue return
* types.
*/
out_param_gvalues = g_value_array_new (out_param_count);
out_param_pos = 0;
out_param_gvalue_pos = 0;
/* Reset argument metadata pointer */
arg_metadata = method_arg_info_from_object_info (object_info, method);
/* Iterate over output arguments again, this time allocating space for
* them as appopriate.
*/
while (*arg_metadata)
{
GValue value = {0, };
GTypeCValue storage;
DBusSignatureIter tmp_sigiter;
GType current_gtype;
arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, NULL, &retval, &argsig);
/* Skip over input arguments and the return value, if any */
if (arg_in || retval != RETVAL_NONE)
continue;
dbus_signature_iter_init (&tmp_sigiter, argsig);
current_gtype = _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE);
g_value_init (&value, G_TYPE_POINTER);
/* We special case variants to make method invocation a bit nicer */
if (current_gtype != G_TYPE_VALUE)
{
memset (&storage, 0, sizeof (storage));
g_array_append_val (out_param_values, storage);
g_value_set_pointer (&value, &(g_array_index (out_param_values, GTypeCValue, out_param_pos)));
out_param_pos++;
}
else
{
g_value_array_append (out_param_gvalues, NULL);
g_value_set_pointer (&value, out_param_gvalues->values + out_param_gvalue_pos);
out_param_gvalue_pos++;
}
g_value_array_append (value_array, &value);
}
}
/* Append GError as final argument if necessary */
if (retval_signals_error)
{
g_assert (have_retval);
g_value_array_append (value_array, NULL);
g_value_init (g_value_array_get_nth (value_array, value_array->n_values - 1), G_TYPE_POINTER);
g_value_set_pointer (g_value_array_get_nth (value_array, value_array->n_values - 1), &gerror);
}
/* Actually invoke method */
method->marshaller (&closure, have_retval ? &return_value : NULL,
value_array->n_values,
value_array->values,
NULL,
#ifdef WINSCW
method->function);
#else
(gpointer)method->function);
#endif
if (call_only)
{
result = DBUS_HANDLER_RESULT_HANDLED;
goto done;
}
if (retval_signals_error)
had_error = _dbus_gvalue_signals_error (&return_value);
else
had_error = FALSE;
if (!had_error)
{
DBusMessageIter iter;
reply = dbus_message_new_method_return (message);
if (reply == NULL)
goto nomem;
/* Append output arguments to reply */
dbus_message_iter_init_append (reply, &iter);
/* First, append the return value, unless it's synthetic */
if (have_retval && !retval_is_synthetic)
{
if (!_dbus_gvalue_marshal (&iter, &return_value))
goto nomem;
if (!retval_is_constant)
g_value_unset (&return_value);
}
/* Grab the argument metadata and iterate over it */
arg_metadata = method_arg_info_from_object_info (object_info, method);
/* Now append any remaining return values */
out_param_pos = 0;
out_param_gvalue_pos = 0;
while (*arg_metadata)
{
GValue gvalue = {0, };
const char *arg_name;
gboolean arg_in;
gboolean constval;
RetvalType retval;
const char *arg_signature;
DBusSignatureIter argsigiter;
do
{
/* Iterate over only output values; skip over input
arguments and the return value */
arg_metadata = arg_iterate (arg_metadata, &arg_name, &arg_in, &constval, &retval, &arg_signature);
}
while ((arg_in || retval != RETVAL_NONE) && *arg_metadata);
/* If the last argument we saw was input or the return
* value, we must be done iterating over output arguments.
*/
if (arg_in || retval != RETVAL_NONE)
break;
dbus_signature_iter_init (&argsigiter, arg_signature);
g_value_init (&gvalue, _dbus_gtype_from_signature_iter (&argsigiter, FALSE));
if (G_VALUE_TYPE (&gvalue) != G_TYPE_VALUE)
{
if (!_dbus_gvalue_take (&gvalue,
&(g_array_index (out_param_values, GTypeCValue, out_param_pos))))
g_assert_not_reached ();
out_param_pos++;
}
else
{
g_value_set_static_boxed (&gvalue, out_param_gvalues->values + out_param_gvalue_pos);
out_param_gvalue_pos++;
}
if (!_dbus_gvalue_marshal (&iter, &gvalue))
goto nomem;
/* Here we actually free the allocated value; we
* took ownership of it with _dbus_gvalue_take, unless
* an annotation has specified this value as constant.
*/
if (!constval)
g_value_unset (&gvalue);
}
}
else
reply = gerror_to_dbus_error_message (object_info, message, gerror);
if (reply)
{
dbus_connection_send (connection, reply, NULL);
dbus_message_unref (reply);
}
result = DBUS_HANDLER_RESULT_HANDLED;
done:
g_free (in_signature);
if (!call_only)
{
g_array_free (out_param_values, TRUE);
g_value_array_free (out_param_gvalues);
}
g_value_array_free (value_array);
return result;
nomem:
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
goto done;
}
static DBusHandlerResult
gobject_message_function (DBusConnection *connection,
DBusMessage *message,
void *user_data)
{
GParamSpec *pspec;
GObject *object;
gboolean setter;
gboolean getter;
char *s;
const char *wincaps_propname;
/* const char *wincaps_propiface; */
DBusMessageIter iter;
const DBusGMethodInfo *method;
const DBusGObjectInfo *object_info;
object = G_OBJECT (user_data);
if (dbus_message_is_method_call (message,
DBUS_INTERFACE_INTROSPECTABLE,
"Introspect"))
return handle_introspect (connection, message, object);
/* Try the metainfo, which lets us invoke methods */
if (lookup_object_and_method (object, message, &object_info, &method))
return invoke_object_method (object, object_info, method, connection, message);
/* If no metainfo, we can still do properties and signals
* via standard GLib introspection
*/
getter = FALSE;
setter = FALSE;
if (dbus_message_is_method_call (message,
DBUS_INTERFACE_PROPERTIES,
"Get"))
getter = TRUE;
else if (dbus_message_is_method_call (message,
DBUS_INTERFACE_PROPERTIES,
"Set"))
setter = TRUE;
if (!(setter || getter))
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
dbus_message_iter_init (message, &iter);
if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
{
g_warning ("Property get or set does not have an interface string as first arg\n");
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
/* We never use the interface name; if we did, we'd need to
* remember that it can be empty string for "pick one for me"
*/
/* dbus_message_iter_get_basic (&iter, &wincaps_propiface); */
dbus_message_iter_next (&iter);
if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
{
g_warning ("Property get or set does not have a property name string as second arg\n");
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
dbus_message_iter_get_basic (&iter, &wincaps_propname);
dbus_message_iter_next (&iter);
s = _dbus_gutils_wincaps_to_uscore (wincaps_propname);
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
s);
g_free (s);
if (pspec != NULL)
{
DBusMessage *ret;
if (setter)
{
if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT)
{
g_warning ("Property set does not have a variant value as third arg\n");
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
ret = set_object_property (connection, message, &iter,
object, pspec);
dbus_message_iter_next (&iter);
}
else if (getter)
{
ret = get_object_property (connection, message,
object, pspec);
}
else
{
g_assert_not_reached ();
ret = NULL;
}
g_assert (ret != NULL);
if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
g_warning ("Property get or set had too many arguments\n");
dbus_connection_send (connection, ret, NULL);
dbus_message_unref (ret);
return DBUS_HANDLER_RESULT_HANDLED;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
static const DBusObjectPathVTable gobject_dbus_vtable = {
gobject_unregister_function,
gobject_message_function,
NULL
};
typedef struct {
GClosure closure;
DBusGConnection *connection;
GObject *object;
const char *signame;
const char *sigiface;
} DBusGSignalClosure;
static GClosure *
dbus_g_signal_closure_new (DBusGConnection *connection,
GObject *object,
const char *signame,
const char *sigiface)
{
DBusGSignalClosure *closure;
closure = (DBusGSignalClosure*) g_closure_new_simple (sizeof (DBusGSignalClosure), NULL);
closure->connection = dbus_g_connection_ref (connection);
closure->object = object;
closure->signame = signame;
closure->sigiface = sigiface;
return (GClosure*) closure;
}
static void
dbus_g_signal_closure_finalize (gpointer data,
GClosure *closure)
{
DBusGSignalClosure *sigclosure = (DBusGSignalClosure *) closure;
dbus_g_connection_unref (sigclosure->connection);
}
static void
signal_emitter_marshaller (GClosure *closure,
GValue *retval,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
DBusGSignalClosure *sigclosure;
DBusMessage *signal;
DBusMessageIter iter;
guint i;
const char *path;
sigclosure = (DBusGSignalClosure *) closure;
g_assert (retval == NULL);
path = _dbus_gobject_get_path (sigclosure->object);
g_assert (path != NULL);
signal = dbus_message_new_signal (path,
sigclosure->sigiface,
sigclosure->signame);
if (!signal)
{
g_error ("out of memory");
return;
}
dbus_message_iter_init_append (signal, &iter);
/* First argument is the object itself, and we can't marshall that */
for (i = 1; i < n_param_values; i++)
{
if (!_dbus_gvalue_marshal (&iter,
(GValue *) (&(param_values[i]))))
{
g_warning ("failed to marshal parameter %d for signal %s",
i, sigclosure->signame);
goto out;
}
}
dbus_connection_send (DBUS_CONNECTION_FROM_G_CONNECTION (sigclosure->connection),
signal, NULL);
out:
dbus_message_unref (signal);
}
static void
export_signals (DBusGConnection *connection, const GList *info_list, GObject *object)
{
GType gtype;
const char *sigdata;
const char *iface;
const char *signame;
const DBusGObjectInfo *info;
gtype = G_TYPE_FROM_INSTANCE (object);
for (; info_list != NULL; info_list = g_list_next (info_list))
{
info = (DBusGObjectInfo *) info_list->data;
sigdata = info->exported_signals;
while (*sigdata != '\0')
{
guint id;
GSignalQuery query;
GClosure *closure;
char *s;
sigdata = propsig_iterate (sigdata, &iface, &signame);
s = _dbus_gutils_wincaps_to_uscore (signame);
id = g_signal_lookup (s, gtype);
if (id == 0)
{
g_warning ("signal \"%s\" (from \"%s\") exported but not found in object class \"%s\"",
s, signame, g_type_name (gtype));
g_free (s);
continue;
}
g_signal_query (id, &query);
if (query.return_type != G_TYPE_NONE)
{
g_warning ("Not exporting signal \"%s\" for object class \"%s\" as it has a return type \"%s\"",
s, g_type_name (gtype), g_type_name (query.return_type));
g_free (s);
continue; /* FIXME: these could be listed as methods ? */
}
closure = dbus_g_signal_closure_new (connection, object, signame, (char*) iface);
g_closure_set_marshal (closure, signal_emitter_marshaller);
g_signal_connect_closure_by_id (object,
id,
0,
closure,
FALSE);
g_closure_add_finalize_notifier (closure, NULL,
dbus_g_signal_closure_finalize);
g_free (s);
}
}
}
#include "dbus-glib-error-switch.h"
/**
* dbus_set_g_error:
* @gerror: an error
* @error: a #DBusError
*
* FIXME
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_set_g_error (GError **gerror,
DBusError *error)
{
int code;
code = dbus_error_to_gerror_code (error->name);
if (code != DBUS_GERROR_REMOTE_EXCEPTION)
g_set_error (gerror, DBUS_GERROR,
code,
"%s",
error->message);
else
g_set_error (gerror, DBUS_GERROR,
code,
"%s%c%s",
error->message ? error->message : "",
'\0',
error->name);
}
static void
dbus_g_error_info_free (gpointer p)
{
DBusGErrorInfo *info;
info = p;
g_free (info->default_iface);
g_free (info);
}
/**
* SECTION:dbus-gobject
* @short_description: Exporting a #GObject remotely
* @see_also: #GObject
* @stability: Stable
*
* FIXME
*/
/**
* dbus_g_object_type_install_info:
* @object_type: #GType for the object
* @info: introspection data generated by #dbus-glib-tool
*
* Install introspection information about the given object #GType
* sufficient to allow methods on the object to be invoked by name.
* The introspection information is normally generated by
* dbus-glib-tool, then this function is called in the
* class_init() for the object class.
*
* Once introspection information has been installed, instances of the
* object registered with #dbus_g_connection_register_g_object() can have
* their methods invoked remotely.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_object_type_install_info (GType object_type,
const DBusGObjectInfo *info)
{
g_return_if_fail (G_TYPE_IS_CLASSED (object_type) || G_TYPE_IS_INTERFACE (object_type));
_dbus_g_value_types_init ();
g_type_set_qdata (object_type,
dbus_g_object_type_dbus_metadata_quark (),
(gpointer) info);
}
/**
* dbus_g_error_domain_register:
* @domain: the #GError domain
* @default_iface: the D-BUS interface used for error values by default, or #NULL
* @code_enum: a #GType for a #GEnum of the error codes
*
* Register a #GError domain and set of codes with D-BUS. You must
* have created a GEnum for the error codes. This function will not
* be needed with an introspection-capable GLib.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_error_domain_register (GQuark domain,
const char *default_iface,
GType code_enum)
{
DBusGErrorInfo *info;
g_return_if_fail (g_quark_to_string (domain) != NULL);
g_return_if_fail (code_enum != G_TYPE_INVALID);
g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM);
g_static_rw_lock_writer_lock (&globals_lock);
if (error_metadata == NULL)
g_datalist_init (&error_metadata);
info = g_datalist_id_get_data (&error_metadata, domain);
if (info != NULL)
{
g_warning ("Metadata for error domain \"%s\" already registered\n",
g_quark_to_string (domain));
}
else
{
info = g_new0 (DBusGErrorInfo, 1);
info->default_iface = g_strdup (default_iface);
info->code_enum = code_enum;
g_datalist_id_set_data_full (&error_metadata,
domain,
info,
dbus_g_error_info_free);
}
g_static_rw_lock_writer_unlock (&globals_lock);
}
static void
unregister_gobject (DBusGConnection *connection, GObject *dead)
{
char *path;
path = g_object_steal_data (dead, "dbus_glib_object_path");
dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection), path);
g_free (path);
}
/**
* dbus_g_connection_register_g_object:
* @connection: the D-BUS connection
* @at_path: the path where the object will live (the object's name)
* @object: the object
*
* Registers a #GObject at the given path. Properties, methods, and signals
* of the object can then be accessed remotely. Methods are only available
* if method introspection data has been added to the object's class
* with g_object_class_install_info().
*
* The registration will be cancelled if either the #DBusConnection or
* the #GObject gets finalized.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_connection_register_g_object (DBusGConnection *connection,
const char *at_path,
GObject *object)
{
GList *info_list;
g_return_if_fail (connection != NULL);
g_return_if_fail (at_path != NULL);
g_return_if_fail (G_IS_OBJECT (object));
info_list = lookup_object_info (object);
if (info_list == NULL)
{
g_warning ("No introspection data registered for object class \"%s\"",
g_type_name (G_TYPE_FROM_INSTANCE (object)));
return;
}
if (!dbus_connection_register_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection),
at_path,
&gobject_dbus_vtable,
object))
{
g_error ("Failed to register GObject with DBusConnection");
return;
}
export_signals (connection, info_list, object);
g_list_free (info_list);
g_object_set_data (object, "dbus_glib_object_path", g_strdup (at_path));
g_object_weak_ref (object, (GWeakNotify)unregister_gobject, connection);
}
/**
* dbus_g_connection_lookup_g_object:
* @connection: a #DBusGConnection
* @at_path: path
*
* FIXME
*
* Returns: the object at path @at_path
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
GObject *
dbus_g_connection_lookup_g_object (DBusGConnection *connection,
const char *at_path)
{
gpointer ret;
if (!dbus_connection_get_object_path_data (DBUS_CONNECTION_FROM_G_CONNECTION (connection), at_path, &ret))
return NULL;
return ret;
}
typedef struct {
GType rettype;
guint n_params;
GType *params;
} DBusGFuncSignature;
static guint
funcsig_hash (gconstpointer key)
{
const DBusGFuncSignature *sig = key;
GType *types;
guint ret;
guint i;
ret = sig->rettype;
types = sig->params;
for (i = 0; i < sig->n_params; i++)
{
ret += (int) (*types);
types++;
}
return ret;
}
static gboolean
funcsig_equal (gconstpointer aval,
gconstpointer bval)
{
const DBusGFuncSignature *a = aval;
const DBusGFuncSignature *b = bval;
const GType *atypes;
const GType *btypes;
guint i;
if (a->rettype != b->rettype
|| a->n_params != b->n_params)
return FALSE;
atypes = a->params;
btypes = b->params;
for (i = 0; i < a->n_params; i++)
{
if (*btypes != *atypes)
return FALSE;
atypes++;
btypes++;
}
return TRUE;
}
static void
funcsig_free (DBusGFuncSignature *sig)
{
g_free (sig->params);
g_free (sig);
}
GClosureMarshal
_dbus_gobject_lookup_marshaller (GType rettype,
guint n_params,
const GType *param_types)
{
GClosureMarshal ret;
DBusGFuncSignature sig;
GType *params;
guint i;
/* Convert to fundamental types */
rettype = G_TYPE_FUNDAMENTAL (rettype);
params = g_new (GType, n_params);
for (i = 0; i < n_params; i++)
params[i] = G_TYPE_FUNDAMENTAL (param_types[i]);
sig.rettype = rettype;
sig.n_params = n_params;
sig.params = params;
g_static_rw_lock_reader_lock (&globals_lock);
if (marshal_table)
#ifdef WINSCW
ret = g_hash_table_lookup (marshal_table, &sig);
#else
ret = (GClosureMarshal)g_hash_table_lookup (marshal_table, &sig);
#endif
else
ret = NULL;
g_static_rw_lock_reader_unlock (&globals_lock);
if (ret == NULL)
{
if (rettype == G_TYPE_NONE)
{
if (n_params == 0)
ret = g_cclosure_marshal_VOID__VOID;
else if (n_params == 1)
{
switch (params[0])
{
case G_TYPE_BOOLEAN:
ret = g_cclosure_marshal_VOID__BOOLEAN;
break;
case G_TYPE_UCHAR:
ret = g_cclosure_marshal_VOID__UCHAR;
break;
case G_TYPE_INT:
ret = g_cclosure_marshal_VOID__INT;
break;
case G_TYPE_UINT:
ret = g_cclosure_marshal_VOID__UINT;
break;
case G_TYPE_DOUBLE:
ret = g_cclosure_marshal_VOID__DOUBLE;
break;
case G_TYPE_STRING:
ret = g_cclosure_marshal_VOID__STRING;
break;
case G_TYPE_BOXED:
ret = g_cclosure_marshal_VOID__BOXED;
break;
}
}
else if (n_params == 3
&& params[0] == G_TYPE_STRING
&& params[1] == G_TYPE_STRING
&& params[2] == G_TYPE_STRING)
{
ret = _dbus_g_marshal_NONE__STRING_STRING_STRING;
}
}
}
g_free (params);
return ret;
}
/**
* dbus_g_object_register_marshaller:
* @marshaller: a GClosureMarshal to be used for invocation
* @rettype: a GType for the return type of the function
* @:... The parameter #GTypes, followed by %G_TYPE_INVALID
*
* Register a #GClosureMarshal to be used for signal invocations,
* giving its return type and a list of parameter types,
* followed by %G_TYPE_INVALID.
*
* This function will not be needed once GLib includes libffi.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_object_register_marshaller (GClosureMarshal marshaller,
GType rettype,
...)
{
va_list args;
GArray *types;
GType gtype;
va_start (args, rettype);
types = g_array_new (TRUE, TRUE, sizeof (GType));
while ((gtype = va_arg (args, GType)) != G_TYPE_INVALID)
g_array_append_val (types, gtype);
dbus_g_object_register_marshaller_array (marshaller, rettype,
types->len, (GType*) types->data);
g_array_free (types, TRUE);
va_end (args);
}
/**
* dbus_g_object_register_marshaller_array:
* @marshaller: a #GClosureMarshal to be used for invocation
* @rettype: a #GType for the return type of the function
* @n_types: number of function parameters
* @types: a C array of GTypes values
*
* Register a #GClosureMarshal to be used for signal invocations.
* @see_also #dbus_g_object_register_marshaller
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_object_register_marshaller_array (GClosureMarshal marshaller,
GType rettype,
guint n_types,
const GType* types)
{
DBusGFuncSignature *sig;
guint i;
g_static_rw_lock_writer_lock (&globals_lock);
if (marshal_table == NULL)
marshal_table = g_hash_table_new_full (funcsig_hash,
funcsig_equal,
(GDestroyNotify) funcsig_free,
NULL);
sig = g_new0 (DBusGFuncSignature, 1);
sig->rettype = G_TYPE_FUNDAMENTAL (rettype);
sig->n_params = n_types;
sig->params = g_new (GType, n_types);
for (i = 0; i < n_types; i++)
sig->params[i] = G_TYPE_FUNDAMENTAL (types[i]);
#ifdef WINSCW
g_hash_table_insert (marshal_table, sig, marshaller);
#else
g_hash_table_insert (marshal_table, sig, (gpointer)marshaller);
#endif
g_static_rw_lock_writer_unlock (&globals_lock);
}
/**
* dbus_g_method_get_sender:
* @context: the method context
*
* Get the sender of a message so we can send a
* "reply" later (i.e. send a message directly
* to a service which invoked the method at a
* later time).
*
* Returns: the unique name of the sender. It
* is up to the caller to free the returned string.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
gchar *
dbus_g_method_get_sender (DBusGMethodInvocation *context)
{
const gchar *sender;
sender = dbus_message_get_sender (dbus_g_message_get_message (context->message));
if (sender == NULL)
return NULL;
return strdup (sender);
}
/**
* dbus_g_method_get_reply:
* @context: the method context
*
* Get the reply message to append reply values
* Used as a sidedoor when you can't generate dbus values
* of the correct type due to glib binding limitations
*
* Returns: a #DBusMessage with the reply
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
DBusMessage *
dbus_g_method_get_reply (DBusGMethodInvocation *context)
{
return dbus_message_new_method_return (dbus_g_message_get_message (context->message));
}
/**
* dbus_g_method_send_reply:
* Send a manually created reply message
* @context: the method context
* @reply: the reply message, will be unreffed
*
* Used as a sidedoor when you can't generate dbus values
* of the correct type due to glib binding limitations
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_method_send_reply (DBusGMethodInvocation *context, DBusMessage *reply)
{
dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
dbus_message_unref (reply);
dbus_g_connection_unref (context->connection);
dbus_g_message_unref (context->message);
g_free (context);
}
/**
* dbus_g_method_return:
* @context: the method context
*
* Send a return message for a given method invocation, with arguments.
* This function also frees the sending context.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_method_return (DBusGMethodInvocation *context, ...)
{
DBusMessage *reply;
DBusMessageIter iter;
va_list args;
char *out_sig;
GArray *argsig;
guint i;
reply = dbus_message_new_method_return (dbus_g_message_get_message (context->message));
out_sig = method_output_signature_from_object_info (context->object, context->method);
argsig = _dbus_gtypes_from_arg_signature (out_sig, FALSE);
dbus_message_iter_init_append (reply, &iter);
va_start (args, context);
for (i = 0; i < argsig->len; i++)
{
GValue value = {0,};
char *error;
g_value_init (&value, g_array_index (argsig, GType, i));
error = NULL;
G_VALUE_COLLECT (&value, args, G_VALUE_NOCOPY_CONTENTS, &error);
if (error)
{
g_warning(error);
g_free (error);
}
_dbus_gvalue_marshal (&iter, &value);
}
va_end (args);
dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
dbus_message_unref (reply);
dbus_g_connection_unref (context->connection);
dbus_g_message_unref (context->message);
g_free (context);
g_free (out_sig);
g_array_free (argsig, TRUE);
}
/**
* dbus_g_method_return_error:
* @context: the method context
* @error: the error to send
*
* Send a error message for a given method invocation.
* This function also frees the sending context.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_method_return_error (DBusGMethodInvocation *context, GError *error)
{
DBusMessage *reply;
reply = gerror_to_dbus_error_message (context->object, dbus_g_message_get_message (context->message), error);
dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
dbus_message_unref (reply);
g_free (context);
}
const char * _dbus_gobject_get_path (GObject *obj)
{
return g_object_get_data (obj, "dbus_glib_object_path");
}
#ifdef DBUS_BUILD_TESTS
#include <stdlib.h>
static void
_dummy_function (void)
{
}
/* Data structures copied from one generated by current dbus-binding-tool;
* we need to support this layout forever
*/
static const DBusGMethodInfo dbus_glib_internal_test_methods[] = {
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 0 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 49 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 117 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 191 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 270 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 320 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 391 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 495 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 623 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 693 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 765 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 838 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 911 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 988 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1064 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1140 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1204 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1278 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1347 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1408 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1460 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1533 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1588 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1647 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1730 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1784 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1833 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1895 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1947 },
{ (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1999 },
};
const DBusGObjectInfo dbus_glib_internal_test_object_info = {
0,
dbus_glib_internal_test_methods,
30,
"org.freedesktop.DBus.Tests.MyObject\0DoNothing\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Increment\0S\0x\0I\0u\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementRetval\0S\0x\0I\0u\0arg1\0O\0F\0R\0u\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementRetvalError\0S\0x\0I\0u\0arg1\0O\0F\0E\0u\0\0org.freedesktop.DBus.Tests.MyObject\0ThrowError\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Uppercase\0S\0arg0\0I\0s\0arg1\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0ManyArgs\0S\0x\0I\0u\0str\0I\0s\0trouble\0I\0d\0d_ret\0O\0F\0N\0d\0str_ret\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0ManyReturn\0S\0arg0\0O\0F\0N\0u\0arg1\0O\0F\0N\0s\0arg2\0O\0F\0N\0i\0arg3\0O\0F\0N\0u\0arg4\0O\0F\0N\0u\0arg5\0O\0C\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0Stringify\0S\0val\0I\0v\0arg1\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0Unstringify\0S\0val\0I\0s\0arg1\0O\0F\0N\0v\0\0org.freedesktop.DBus.Tests.MyObject\0Recursive1\0S\0arg0\0I\0au\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0Recursive2\0S\0arg0\0I\0u\0arg1\0O\0F\0N\0au\0\0org.freedesktop.DBus.Tests.MyObject\0ManyUppercase\0S\0arg0\0I\0as\0arg1\0O\0F\0N\0as\0\0org.freedesktop.DBus.Tests.MyObject\0StrHashLen\0S\0arg0\0I\0a{ss}\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0SendCar\0S\0arg0\0I\0(suv)\0arg1\0O\0F\0N\0(uo)\0\0org.freedesktop.DBus.Tests.MyObject\0GetHash\0S\0arg0\0O\0F\0N\0a{ss}\0\0org.freedesktop.DBus.Tests.MyObject\0RecArrays\0S\0val\0I\0aas\0arg1\0O\0F\0N\0aau\0\0org.freedesktop.DBus.Tests.MyObject\0Objpath\0S\0arg0\0I\0o\0arg1\0O\0C\0N\0o\0\0org.freedesktop.DBus.Tests.MyObject\0GetObjs\0S\0arg0\0O\0F\0N\0ao\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementVal\0S\0\0org.freedesktop.DBus.Tests.MyObject\0AsyncIncrement\0A\0x\0I\0u\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0AsyncThrowError\0A\0\0org.freedesktop.DBus.Tests.MyObject\0GetVal\0S\0arg0\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0ManyStringify\0S\0arg0\0I\0a{sv}\0arg1\0O\0F\0N\0a{sv}\0\0org.freedesktop.DBus.Tests.MyObject\0EmitFrobnicate\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Terminate\0S\0\0org.freedesktop.DBus.Tests.FooObject\0GetValue\0S\0arg0\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.FooObject\0EmitSignals\0S\0\0org.freedesktop.DBus.Tests.FooObject\0EmitSignal2\0S\0\0org.freedesktop.DBus.Tests.FooObject\0Terminate\0S\0\0\0",
"org.freedesktop.DBus.Tests.MyObject\0Frobnicate\0org.freedesktop.DBus.Tests.FooObject\0Sig0\0org.freedesktop.DBus.Tests.FooObject\0Sig1\0org.freedesktop.DBus.Tests.FooObject\0Sig2\0\0",
"\0"
};
/**
* @ingroup DBusGLibInternals
* Unit test for GLib GObject integration ("skeletons")
* Returns: #TRUE on success.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
gboolean
_dbus_gobject_test (const char *test_data_dir)
{
int i;
const char *arg;
const char *arg_name;
gboolean arg_in;
gboolean constval;
RetvalType retval;
const char *arg_signature;
const char *sigdata;
const char *iface;
const char *signame;
static struct { const char *wincaps; const char *uscore; } name_pairs[] = {
{ "SetFoo", "set_foo" },
{ "Foo", "foo" },
{ "GetFooBar", "get_foo_bar" },
{ "Hello", "hello" }
/* Impossible-to-handle cases */
/* { "FrobateUIHandler", "frobate_ui_handler" } */
};
/* Test lookup in our hardcoded object info; if these tests fail
* then it likely means you changed the generated object info in an
* incompatible way and broke the lookup functions. In that case
* you need to bump the version and use a new structure instead. */
/* DoNothing */
arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
&(dbus_glib_internal_test_methods[0]));
g_assert (*arg == '\0');
/* Increment */
arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
&(dbus_glib_internal_test_methods[1]));
g_assert (*arg != '\0');
arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
g_assert (!strcmp (arg_name, "x"));
g_assert (arg_in == TRUE);
g_assert (!strcmp (arg_signature, "u"));
g_assert (*arg != '\0');
arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
g_assert (arg_in == FALSE);
g_assert (retval == RETVAL_NONE);
g_assert (!strcmp (arg_signature, "u"));
g_assert (*arg == '\0');
/* IncrementRetval */
arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
&(dbus_glib_internal_test_methods[2]));
g_assert (*arg != '\0');
arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
g_assert (!strcmp (arg_name, "x"));
g_assert (arg_in == TRUE);
g_assert (!strcmp (arg_signature, "u"));
g_assert (*arg != '\0');
arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
g_assert (retval == RETVAL_NOERROR);
g_assert (arg_in == FALSE);
g_assert (!strcmp (arg_signature, "u"));
g_assert (*arg == '\0');
/* IncrementRetvalError */
arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
&(dbus_glib_internal_test_methods[3]));
g_assert (*arg != '\0');
arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
g_assert (!strcmp (arg_name, "x"));
g_assert (arg_in == TRUE);
g_assert (!strcmp (arg_signature, "u"));
g_assert (*arg != '\0');
arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
g_assert (retval == RETVAL_ERROR);
g_assert (arg_in == FALSE);
g_assert (!strcmp (arg_signature, "u"));
g_assert (*arg == '\0');
/* Stringify */
arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
&(dbus_glib_internal_test_methods[8]));
g_assert (*arg != '\0');
arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
g_assert (!strcmp (arg_name, "val"));
g_assert (arg_in == TRUE);
g_assert (!strcmp (arg_signature, "v"));
g_assert (*arg != '\0');
arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
g_assert (retval == RETVAL_NONE);
g_assert (arg_in == FALSE);
g_assert (!strcmp (arg_signature, "s"));
g_assert (*arg == '\0');
sigdata = dbus_glib_internal_test_object_info.exported_signals;
g_assert (*sigdata != '\0');
sigdata = propsig_iterate (sigdata, &iface, &signame);
g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
g_assert (!strcmp (signame, "Frobnicate"));
g_assert (*sigdata != '\0');
sigdata = propsig_iterate (sigdata, &iface, &signame);
g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
g_assert (!strcmp (signame, "Sig0"));
g_assert (*sigdata != '\0');
sigdata = propsig_iterate (sigdata, &iface, &signame);
g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
g_assert (!strcmp (signame, "Sig1"));
g_assert (*sigdata != '\0');
sigdata = propsig_iterate (sigdata, &iface, &signame);
g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
g_assert (!strcmp (signame, "Sig2"));
g_assert (*sigdata == '\0');
i = 0;
while (i < (int) G_N_ELEMENTS (name_pairs))
{
char *uscore;
char *wincaps;
uscore = _dbus_gutils_wincaps_to_uscore (name_pairs[i].wincaps);
wincaps = uscore_to_wincaps (name_pairs[i].uscore);
if (strcmp (uscore, name_pairs[i].uscore) != 0)
{
g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
name_pairs[i].wincaps, name_pairs[i].uscore,
uscore);
exit (1);
}
if (strcmp (wincaps, name_pairs[i].wincaps) != 0)
{
g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
name_pairs[i].uscore, name_pairs[i].wincaps,
wincaps);
exit (1);
}
g_free (uscore);
g_free (wincaps);
++i;
}
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */