summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2014-03-14 19:19:34 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2014-03-26 18:20:58 +0000
commit225806386dd163b35b8cc8d3fdccb9434709c99d (patch)
tree95bc177a90f1cb8c63eb22a4dd082aa98f24c5bc
parent7ee8429d49a8b625b3fa8c41a0a9f47e8c547d00 (diff)
TpSvcInterfaceInfo, TpSvcInterfaceSkeleton: add
These will let us export TpSvc objects as GDBus objects. TpSvcInterfaceSkeleton is private, so it's OK that it makes assumptions about how TpDBusDaemon will manage its life-cycle.
-rw-r--r--docs/reference/telepathy-glib/telepathy-glib-docs.sgml1
-rw-r--r--docs/reference/telepathy-glib/telepathy-glib-sections.txt9
-rw-r--r--telepathy-glib/Makefile.am4
-rw-r--r--telepathy-glib/core-svc-interface.c106
-rw-r--r--telepathy-glib/core-svc-interface.h50
-rw-r--r--telepathy-glib/debug-internal.h3
-rw-r--r--telepathy-glib/debug.c2
-rw-r--r--telepathy-glib/svc-interface-skeleton-internal.h71
-rw-r--r--telepathy-glib/svc-interface-skeleton.c243
-rw-r--r--telepathy-glib/telepathy-glib.h1
10 files changed, 489 insertions, 1 deletions
diff --git a/docs/reference/telepathy-glib/telepathy-glib-docs.sgml b/docs/reference/telepathy-glib/telepathy-glib-docs.sgml
index b72135681..c9d740bfb 100644
--- a/docs/reference/telepathy-glib/telepathy-glib-docs.sgml
+++ b/docs/reference/telepathy-glib/telepathy-glib-docs.sgml
@@ -177,6 +177,7 @@
<chapter id="ch-service-dbus">
<title>Low-level generated code - service-side</title>
<xi:include href="tp-svc.xml"/>
+ <xi:include href="xml/core-svc-interface.xml"/>
<xi:include href="xml/svc-channel.xml"/>
<xi:include href="xml/svc-channel-group.xml"/>
diff --git a/docs/reference/telepathy-glib/telepathy-glib-sections.txt b/docs/reference/telepathy-glib/telepathy-glib-sections.txt
index d8ece0bc5..f07c63f9c 100644
--- a/docs/reference/telepathy-glib/telepathy-glib-sections.txt
+++ b/docs/reference/telepathy-glib/telepathy-glib-sections.txt
@@ -6331,3 +6331,12 @@ tp_cli_logger_add_signals
<SUBSECTION Private>
TpLoggerPriv
</SECTION>
+
+<SECTION>
+<INCLUDE>telepathy-glib/telepathy-glib.h</INCLUDE>
+<TITLE>TpSvcInterface</TITLE>
+<FILE>core-svc-interface</FILE>
+TpSvcInterfaceInfo
+tp_svc_interface_peek_dbus_interface_info
+tp_svc_interface_set_dbus_interface_info
+</SECTION>
diff --git a/telepathy-glib/Makefile.am b/telepathy-glib/Makefile.am
index 418818ce2..3aae81205 100644
--- a/telepathy-glib/Makefile.am
+++ b/telepathy-glib/Makefile.am
@@ -85,6 +85,7 @@ tpginclude_HEADERS = \
contact.h \
contact-operations.h \
base-contact-list.h \
+ core-svc-interface.h \
dbus.h \
dbus-daemon.h \
dbus-properties-mixin.h \
@@ -190,6 +191,7 @@ libtelepathy_glib_core_internal_la_LIBADD = $(ALL_LIBS)
libtelepathy_glib_core_internal_la_SOURCES = \
core-dbus.c \
core-proxy.c \
+ core-svc-interface.c \
core-util.c \
errors.c \
$(NULL)
@@ -335,6 +337,8 @@ libtelepathy_glib_main_internal_la_SOURCES = \
stream-tube-channel.c \
stream-tube-connection-internal.h \
stream-tube-connection.c \
+ svc-interface-skeleton.c \
+ svc-interface-skeleton-internal.h \
text-channel.c \
tls-certificate.c \
tls-certificate-rejection.c \
diff --git a/telepathy-glib/core-svc-interface.c b/telepathy-glib/core-svc-interface.c
new file mode 100644
index 000000000..ec9820aab
--- /dev/null
+++ b/telepathy-glib/core-svc-interface.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2014 Collabora Ltd.
+ *
+ * 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+#include <telepathy-glib/core-svc-interface.h>
+
+/**
+ * SECTION:core-svc-interface
+ * @title: TpSvcInterface
+ * @short_description: glue to export `TpSvc` interfaces on D-Bus
+ *
+ * #TpSvcInterfaceInfo describes a dbus-glib-style #GInterface in sufficient
+ * detail to export it on a #GDBusConnection.
+ *
+ * Since: 0.UNRELEASED
+ */
+
+/**
+ * TpSvcInterfaceInfo: (skip)
+ * @ref_count: currently -1 since these structures can only be statically
+ * allocated; will be used for the reference count in the same way
+ * as #GDBusInterfaceInfo if necessary
+ * @interface_info: the GDBus interface information
+ * @vtable: the GDBus vtable, which must expect the object that
+ * implements the `TpSvc` interface (*not* the #GDBusInterfaceSkeleton!)
+ * as its `user_data`
+ * @signals: (array zero-terminated=1): a %NULL-terminated array of
+ * GLib signal names in the same order as `interface_info->signals`
+ *
+ * The necessary glue between a dbus-glib-style `TpSvc` #GInterface
+ * and telepathy-glib.
+ *
+ * These structs are intended to be programmatically-generated.
+ */
+
+static GQuark
+quark (void)
+{
+ static GQuark q = 0;
+
+ if (G_UNLIKELY (q == 0))
+ {
+ q = g_quark_from_static_string (
+ "tp_svc_interface_set_dbus_interface_info");
+ }
+
+ return q;
+}
+
+/**
+ * tp_svc_interface_peek_dbus_interface_info: (skip)
+ * @g_interface: The #GType of a service interface
+ *
+ * See whether the given interface has Telepathy code generation data
+ * attached.
+ *
+ * Returns: (transfer null): a #TpSvcInterfaceInfo struct, or %NULL
+ */
+const TpSvcInterfaceInfo *
+tp_svc_interface_peek_dbus_interface_info (GType g_interface)
+{
+ return g_type_get_qdata (g_interface, quark ());
+}
+
+/**
+ * tp_svc_interface_set_dbus_interface_info: (skip)
+ * @g_interface: The #GType of a service interface
+ * @info: struct encapsulating the #GDBusInterfaceInfo, the #GDBusVTable
+ * and the GLib signal names corresponding to D-Bus signals
+ * @vtable: the vtable, whose methods must expect the object
+ * implementing @g_interface as their user-data
+ *
+ * Declare that @g_interface implements the given D-Bus interface, with the
+ * given vtable. This may only be called once per GInterface, usually from
+ * a section of its base_init function that only runs once.
+ *
+ * This is typically only used within generated code; there is normally no
+ * reason to call it manually.
+ */
+void
+tp_svc_interface_set_dbus_interface_info (GType g_interface,
+ const TpSvcInterfaceInfo *info)
+{
+ g_return_if_fail (G_TYPE_IS_INTERFACE (g_interface));
+ g_return_if_fail (info->ref_count == -1);
+ g_return_if_fail (tp_svc_interface_peek_dbus_interface_info (g_interface)
+ == NULL);
+
+ /* g_type_set_qdata wants a non-const pointer */
+ g_type_set_qdata (g_interface, quark (), (gpointer) info);
+}
diff --git a/telepathy-glib/core-svc-interface.h b/telepathy-glib/core-svc-interface.h
new file mode 100644
index 000000000..dd5d7933f
--- /dev/null
+++ b/telepathy-glib/core-svc-interface.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2014 Collabora Ltd.
+ *
+ * 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if !defined (_TP_GLIB_H_INSIDE) && !defined (_TP_COMPILATION)
+#error "Only <telepathy-glib/telepathy-glib.h> can be included directly."
+#endif
+
+#ifndef __TP_CORE_SVC_INTERFACE_H__
+#define __TP_CORE_SVC_INTERFACE_H__
+
+#include <gio/gio.h>
+
+#include <telepathy-glib/defs.h>
+
+G_BEGIN_DECLS
+
+typedef struct _TpSvcInterfaceInfo TpSvcInterfaceInfo;
+
+struct _TpSvcInterfaceInfo {
+ volatile gint ref_count;
+ GDBusInterfaceInfo *interface_info;
+ GDBusInterfaceVTable *vtable;
+ gchar **signals;
+ gpointer _reserved[8];
+};
+
+void tp_svc_interface_set_dbus_interface_info (GType type,
+ const TpSvcInterfaceInfo *info);
+
+const TpSvcInterfaceInfo *tp_svc_interface_peek_dbus_interface_info (
+ GType type);
+
+G_END_DECLS
+
+#endif
diff --git a/telepathy-glib/debug-internal.h b/telepathy-glib/debug-internal.h
index 7e756844d..0e09b070f 100644
--- a/telepathy-glib/debug-internal.h
+++ b/telepathy-glib/debug-internal.h
@@ -36,7 +36,8 @@ typedef enum
TP_DEBUG_CALL = 1 << 18,
/* Quis custodiet ipsos custodes? */
TP_DEBUG_DEBUGGER = 1 << 19,
- TP_DEBUG_TLS = 1 << 20
+ TP_DEBUG_TLS = 1 << 20,
+ TP_DEBUG_SVC = 1 << 21
} TpDebugFlags;
gboolean _tp_debug_flag_is_set (TpDebugFlags flag);
diff --git a/telepathy-glib/debug.c b/telepathy-glib/debug.c
index 62099558f..f8ffc66da 100644
--- a/telepathy-glib/debug.c
+++ b/telepathy-glib/debug.c
@@ -104,6 +104,7 @@ static GDebugKey keys[] = {
{ "call", TP_DEBUG_CALL },
{ "debugger", TP_DEBUG_DEBUGGER },
{ "tls", TP_DEBUG_TLS },
+ { "svc", TP_DEBUG_SVC },
{ 0, }
};
@@ -139,6 +140,7 @@ static DebugKeyToDomain key_to_domain[] = {
{ TP_DEBUG_ROOM_CONFIG, G_LOG_DOMAIN "/room-config" },
{ TP_DEBUG_DEBUGGER, G_LOG_DOMAIN "/debugger" },
{ TP_DEBUG_TLS, G_LOG_DOMAIN "/tls" },
+ { TP_DEBUG_SVC, G_LOG_DOMAIN "/svc" },
{ 0, NULL }
};
diff --git a/telepathy-glib/svc-interface-skeleton-internal.h b/telepathy-glib/svc-interface-skeleton-internal.h
new file mode 100644
index 000000000..0fb2dd736
--- /dev/null
+++ b/telepathy-glib/svc-interface-skeleton-internal.h
@@ -0,0 +1,71 @@
+/*<private_header>*/
+/*
+ * Copyright © 2014 Collabora Ltd.
+ *
+ * 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __TP_SVC_INTERFACE_SKELETON_INTERNAL_H__
+#define __TP_SVC_INTERFACE_SKELETON_INTERNAL_H__
+
+#include <gio/gio.h>
+
+#include <telepathy-glib/core-svc-interface.h>
+#include <telepathy-glib/defs.h>
+
+G_BEGIN_DECLS
+
+typedef struct _TpSvcInterfaceSkeleton TpSvcInterfaceSkeleton;
+typedef struct _TpSvcInterfaceSkeletonClass TpSvcInterfaceSkeletonClass;
+typedef struct _TpSvcInterfaceSkeletonPrivate TpSvcInterfaceSkeletonPrivate;
+
+GType _tp_svc_interface_skeleton_get_type (void);
+
+#define TP_TYPE_SVC_INTERFACE_SKELETON \
+ (_tp_svc_interface_skeleton_get_type ())
+#define TP_SVC_INTERFACE_SKELETON(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TYPE_SVC_INTERFACE_SKELETON, \
+ TpSvcInterfaceSkeleton))
+#define TP_SVC_INTERFACE_SKELETON_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TYPE_SVC_INTERFACE_SKELETON, \
+ TpSvcInterfaceSkeletonClass))
+#define TP_IS_SVC_INTERFACE_SKELETON(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TYPE_SVC_INTERFACE_SKELETON))
+#define TP_IS_SVC_INTERFACE_SKELETON_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TYPE_SVC_INTERFACE_SKELETON))
+#define TP_SVC_INTERFACE_SKELETON_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TYPE_SVC_INTERFACE_SKELETON, \
+ TpSvcInterfaceSkeletonClass))
+
+struct _TpSvcInterfaceSkeletonClass
+{
+ /*< private >*/
+ GDBusInterfaceSkeletonClass parent_class;
+};
+
+struct _TpSvcInterfaceSkeleton
+{
+ /*< private >*/
+ GDBusInterfaceSkeleton parent;
+ TpSvcInterfaceSkeletonPrivate *priv;
+};
+
+TpSvcInterfaceSkeleton *_tp_svc_interface_skeleton_new (gpointer object,
+ GType iface,
+ const TpSvcInterfaceInfo *iinfo);
+
+G_END_DECLS
+
+#endif
diff --git a/telepathy-glib/svc-interface-skeleton.c b/telepathy-glib/svc-interface-skeleton.c
new file mode 100644
index 000000000..547a360f6
--- /dev/null
+++ b/telepathy-glib/svc-interface-skeleton.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright © 2014 Collabora Ltd.
+ *
+ * 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+#include <telepathy-glib/svc-interface-skeleton-internal.h>
+
+#include <dbus/dbus-glib.h>
+
+#include <telepathy-glib/dbus-properties-mixin.h>
+#include <telepathy-glib/variant-util.h>
+
+#define DEBUG_FLAG TP_DEBUG_SVC
+#include "debug-internal.h"
+
+struct _TpSvcInterfaceSkeletonPrivate
+{
+ GWeakRef object;
+ TpSvcInterfaceInfo *iinfo;
+};
+
+G_DEFINE_TYPE (TpSvcInterfaceSkeleton, _tp_svc_interface_skeleton,
+ G_TYPE_DBUS_INTERFACE_SKELETON)
+
+static void
+_tp_svc_interface_skeleton_init (TpSvcInterfaceSkeleton *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ TP_TYPE_SVC_INTERFACE_SKELETON, TpSvcInterfaceSkeletonPrivate);
+}
+
+static void
+tp_svc_interface_skeleton_dispose (GObject *obj)
+{
+ TpSvcInterfaceSkeleton *self = TP_SVC_INTERFACE_SKELETON (obj);
+
+ /* not using g_weak_ref_clear() in order to be idempotent */
+ g_weak_ref_set (&self->priv->object, NULL);
+
+ G_OBJECT_CLASS (_tp_svc_interface_skeleton_parent_class)->dispose (obj);
+}
+
+static GDBusInterfaceInfo *
+tp_svc_interface_skeleton_get_info (GDBusInterfaceSkeleton *skel)
+{
+ TpSvcInterfaceSkeleton *self = TP_SVC_INTERFACE_SKELETON (skel);
+
+ return self->priv->iinfo->interface_info;
+}
+
+static void
+tp_svc_interface_skeleton_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ TpSvcInterfaceSkeleton *self = TP_SVC_INTERFACE_SKELETON (user_data);
+ GObject *object;
+
+ DEBUG ("%s.%s on %s %p from %s", interface_name, method_name, object_path,
+ self, sender);
+
+ object = g_weak_ref_get (&self->priv->object);
+ /* TpDBusDaemon is meant to unexport us automatically when the object
+ * goes away */
+ g_return_if_fail (object != NULL);
+
+ self->priv->iinfo->vtable->method_call (connection,
+ sender, object_path, interface_name, method_name, parameters,
+ invocation, object);
+ g_object_unref (object);
+}
+
+static GDBusInterfaceVTable vtable = {
+ tp_svc_interface_skeleton_method_call,
+ NULL,
+ NULL
+};
+
+static GDBusInterfaceVTable *
+tp_svc_interface_skeleton_get_vtable (GDBusInterfaceSkeleton *skel)
+{
+ return &vtable;
+}
+
+static GVariant *
+tp_svc_interface_skeleton_get_properties (GDBusInterfaceSkeleton *skel)
+{
+ TpSvcInterfaceSkeleton *self = TP_SVC_INTERFACE_SKELETON (skel);
+ GVariant *ret;
+ GHashTable *asv;
+ const gchar *iface_name = self->priv->iinfo->interface_info->name;
+
+ /* For now assume we have the TpDBusPropertiesMixin if we have
+ * any properties at all. This never returns NULL. */
+ asv = tp_dbus_properties_mixin_dup_all ((GObject *) self, iface_name);
+
+ ret = g_variant_ref_sink (tp_asv_to_vardict (asv));
+ g_hash_table_unref (asv);
+ return ret;
+}
+
+static void
+tp_svc_interface_skeleton_flush (GDBusInterfaceSkeleton *skel)
+{
+ /* stub: we emit any changes immediately, and we implement Properties
+ * elsewhere anyway */
+}
+
+static void
+_tp_svc_interface_skeleton_class_init (TpSvcInterfaceSkeletonClass *cls)
+{
+ GObjectClass *obj_cls = G_OBJECT_CLASS (cls);
+ GDBusInterfaceSkeletonClass *skel_cls = G_DBUS_INTERFACE_SKELETON_CLASS (cls);
+
+ g_type_class_add_private (cls, sizeof (TpSvcInterfaceSkeleton));
+
+ obj_cls->dispose = tp_svc_interface_skeleton_dispose;
+
+ skel_cls->get_info = tp_svc_interface_skeleton_get_info;
+ skel_cls->get_vtable = tp_svc_interface_skeleton_get_vtable;
+ skel_cls->get_properties = tp_svc_interface_skeleton_get_properties;
+ skel_cls->flush = tp_svc_interface_skeleton_flush;
+}
+
+typedef struct {
+ GClosure closure;
+ /* (transfer none) - the closure ensures we have a ref */
+ TpSvcInterfaceSkeleton *self;
+ /* (transfer none) - borrowed from the interface info */
+ const gchar *name;
+} SignalClosure;
+
+static void
+tp_svc_interface_skeleton_emit_signal (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ SignalClosure *sc = (SignalClosure *) closure;
+ TpSvcInterfaceSkeleton *self = sc->self;
+ GDBusInterfaceSkeleton *skel = G_DBUS_INTERFACE_SKELETON (self);
+ const gchar *path = g_dbus_interface_skeleton_get_object_path (skel);
+ GVariantBuilder builder;
+ guint i;
+
+ DEBUG ("%s.%s from %s %p", self->priv->iinfo->interface_info->name,
+ sc->name, path, self);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
+
+ /* Skip parameter 0, which is the GObject. */
+ for (i = 1; i < n_param_values; i++)
+ g_variant_builder_add_value (&builder,
+ dbus_g_value_build_g_variant (param_values + i));
+
+ /* we only support being exported on one connection */
+ g_dbus_connection_emit_signal (
+ g_dbus_interface_skeleton_get_connection (skel),
+ NULL, /* broadcast */
+ g_dbus_interface_skeleton_get_object_path (skel),
+ self->priv->iinfo->interface_info->name,
+ sc->name,
+ /* consume floating ref */
+ g_variant_builder_end (&builder),
+ /* cannot fail unless a parameter is incompatible with D-Bus,
+ * so ignore error */
+ NULL);
+}
+
+/*
+ * _tp_svc_interface_skeleton_new: (skip)
+ * @object: (type GObject.Object): a #GObject
+ * @iface: a `TpSvc` interface on the object
+ * @iinfo: a description of the corresponding D-Bus interface
+ *
+ * Returns: (transfer full): a new interface skeleton wrapping @iface
+ * on @object
+ */
+TpSvcInterfaceSkeleton *
+_tp_svc_interface_skeleton_new (gpointer object,
+ GType iface,
+ const TpSvcInterfaceInfo *iinfo)
+{
+ TpSvcInterfaceSkeleton *self;
+
+ /* not bothering to refcount it, it must be static for now */
+ g_return_val_if_fail (iinfo->ref_count == -1, NULL);
+
+ self = g_object_new (TP_TYPE_SVC_INTERFACE_SKELETON,
+ NULL);
+ g_weak_ref_init (&self->priv->object, object);
+ self->priv->iinfo = (TpSvcInterfaceInfo *) iinfo;
+
+ if (iinfo->signals != NULL)
+ {
+ guint i;
+
+ for (i = 0; iinfo->signals[i] != NULL; i++)
+ {
+ const gchar *glib_name;
+ const gchar *dbus_name;
+ SignalClosure *closure;
+
+ g_assert (iinfo->interface_info->signals[i] != NULL);
+
+ glib_name = iinfo->signals[i];
+ dbus_name = iinfo->interface_info->signals[i]->name;
+
+ closure = (SignalClosure *) g_closure_new_object (sizeof (*closure),
+ (GObject *) self);
+ g_closure_set_marshal ((GClosure *) closure,
+ tp_svc_interface_skeleton_emit_signal);
+ closure->self = self;
+ closure->name = dbus_name;
+
+ g_signal_connect_closure (object, glib_name, (GClosure *) closure,
+ FALSE);
+ }
+ }
+
+ return self;
+}
diff --git a/telepathy-glib/telepathy-glib.h b/telepathy-glib/telepathy-glib.h
index 4d099ba55..ab853639b 100644
--- a/telepathy-glib/telepathy-glib.h
+++ b/telepathy-glib/telepathy-glib.h
@@ -66,6 +66,7 @@
#include <telepathy-glib/channel.h>
#include <telepathy-glib/client.h>
#include <telepathy-glib/client-message.h>
+#include <telepathy-glib/core-svc-interface.h>
#include <telepathy-glib/cm-message.h>
#include <telepathy-glib/connection-contact-list.h>
#include <telepathy-glib/connection-manager.h>