[Telepathy-commits] [telepathy-glib/master] Add the beginnings of a StreamedMedia demo connection manager
Simon McVittie
simon.mcvittie at collabora.co.uk
Tue Mar 10 04:32:29 PDT 2009
---
configure.ac | 1 +
examples/cm/Makefile.am | 1 +
examples/cm/callable/Makefile.am | 66 ++++
examples/cm/callable/conn.c | 383 ++++++++++++++++++++
examples/cm/callable/conn.h | 78 ++++
examples/cm/callable/connection-manager.c | 125 +++++++
examples/cm/callable/connection-manager.h | 73 ++++
examples/cm/callable/main.c | 54 +++
examples/cm/callable/manager-file.py | 19 +
examples/cm/callable/media-channel.c | 546 +++++++++++++++++++++++++++++
examples/cm/callable/media-channel.h | 74 ++++
examples/cm/callable/media-manager.c | 400 +++++++++++++++++++++
examples/cm/callable/media-manager.h | 71 ++++
13 files changed, 1891 insertions(+), 0 deletions(-)
create mode 100644 examples/cm/callable/Makefile.am
create mode 100644 examples/cm/callable/conn.c
create mode 100644 examples/cm/callable/conn.h
create mode 100644 examples/cm/callable/connection-manager.c
create mode 100644 examples/cm/callable/connection-manager.h
create mode 100644 examples/cm/callable/main.c
create mode 100644 examples/cm/callable/manager-file.py
create mode 100644 examples/cm/callable/media-channel.c
create mode 100644 examples/cm/callable/media-channel.h
create mode 100644 examples/cm/callable/media-manager.c
create mode 100644 examples/cm/callable/media-manager.h
diff --git a/configure.ac b/configure.ac
index 2a6118a..8840c58 100644
--- a/configure.ac
+++ b/configure.ac
@@ -200,6 +200,7 @@ AC_OUTPUT( Makefile \
examples/Makefile \
examples/client/Makefile \
examples/cm/Makefile \
+ examples/cm/callable/Makefile \
examples/cm/channelspecific/Makefile \
examples/cm/contactlist/Makefile \
examples/cm/echo/Makefile \
diff --git a/examples/cm/Makefile.am b/examples/cm/Makefile.am
index 2da3990..5cae88c 100644
--- a/examples/cm/Makefile.am
+++ b/examples/cm/Makefile.am
@@ -1,4 +1,5 @@
SUBDIRS = \
+ callable \
channelspecific \
contactlist \
echo \
diff --git a/examples/cm/callable/Makefile.am b/examples/cm/callable/Makefile.am
new file mode 100644
index 0000000..a60ef40
--- /dev/null
+++ b/examples/cm/callable/Makefile.am
@@ -0,0 +1,66 @@
+# Example connection manager with audio/video calls.
+
+EXAMPLES = telepathy-example-cm-callable
+noinst_LTLIBRARIES = libexample-cm-callable.la
+
+if INSTALL_EXAMPLES
+libexec_PROGRAMS = $(EXAMPLES)
+else
+noinst_PROGRAMS = $(EXAMPLES)
+endif
+
+libexample_cm_callable_la_SOURCES = \
+ conn.c \
+ conn.h \
+ connection-manager.c \
+ connection-manager.h \
+ media-channel.c \
+ media-channel.h \
+ media-manager.c \
+ media-manager.h
+
+# In an external project you'd use $(TP_GLIB_LIBS) (obtained from
+# pkg-config via autoconf) instead of the .la path
+libexample_cm_callable_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(DBUS_LIBS) \
+ $(top_builddir)/telepathy-glib/libtelepathy-glib.la
+
+telepathy_example_cm_callable_SOURCES = \
+ main.c
+
+telepathy_example_cm_callable_LDADD = \
+ $(noinst_LTLIBRARIES)
+
+AM_CFLAGS = \
+ $(ERROR_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(TP_GLIB_CFLAGS)
+
+EXTRA_DIST = manager-file.py
+
+servicedir = ${datadir}/dbus-1/services
+
+if INSTALL_EXAMPLES
+service_DATA = _gen/org.freedesktop.Telepathy.ConnectionManager.example_callable.service
+$(service_DATA): %: Makefile
+ $(mkdir_p) _gen
+ { echo "[D-BUS Service]" && \
+ echo "Name=org.freedesktop.Telepathy.ConnectionManager.example_callable" && \
+ echo "Exec=${libexecdir}/telepathy-example-cm-callable"; } > $@
+
+managerdir = ${datadir}/telepathy/managers
+manager_DATA = _gen/example_callable.manager
+endif
+
+_gen/example_callable.manager _gen/param-spec-struct.h: \
+ manager-file.py $(top_srcdir)/tools/manager-file.py
+ $(mkdir_p) _gen
+ $(PYTHON) $(top_srcdir)/tools/manager-file.py $(srcdir)/manager-file.py _gen
+
+BUILT_SOURCES = _gen/param-spec-struct.h
+CLEANFILES = $(BUILT_SOURCES)
+
+clean-local:
+ rm -rf _gen
diff --git a/examples/cm/callable/conn.c b/examples/cm/callable/conn.c
new file mode 100644
index 0000000..e9d6e43
--- /dev/null
+++ b/examples/cm/callable/conn.c
@@ -0,0 +1,383 @@
+/*
+ * conn.c - an example connection
+ *
+ * Copyright © 2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright © 2007-2009 Nokia Corporation
+ *
+ * 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 "conn.h"
+
+#include <string.h>
+
+#include <dbus/dbus-glib.h>
+
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/errors.h>
+#include <telepathy-glib/handle-repo-dynamic.h>
+#include <telepathy-glib/handle-repo-static.h>
+#include <telepathy-glib/interfaces.h>
+
+#include "media-manager.h"
+
+G_DEFINE_TYPE_WITH_CODE (ExampleCallableConnection,
+ example_callable_connection,
+ TP_TYPE_BASE_CONNECTION,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS,
+ tp_contacts_mixin_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_PRESENCE,
+ tp_presence_mixin_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_SIMPLE_PRESENCE,
+ tp_presence_mixin_simple_presence_iface_init))
+
+enum
+{
+ PROP_ACCOUNT = 1,
+ N_PROPS
+};
+
+struct _ExampleCallableConnectionPrivate
+{
+ gchar *account;
+ gboolean away;
+ gchar *presence_message;
+};
+
+static void
+example_callable_connection_init (ExampleCallableConnection *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ EXAMPLE_TYPE_CALLABLE_CONNECTION,
+ ExampleCallableConnectionPrivate);
+ self->priv->away = FALSE;
+ self->priv->presence_message = g_strdup ("");
+}
+
+static void
+get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *spec)
+{
+ ExampleCallableConnection *self = EXAMPLE_CALLABLE_CONNECTION (object);
+
+ switch (property_id)
+ {
+ case PROP_ACCOUNT:
+ g_value_set_string (value, self->priv->account);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec);
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *spec)
+{
+ ExampleCallableConnection *self = EXAMPLE_CALLABLE_CONNECTION (object);
+
+ switch (property_id)
+ {
+ case PROP_ACCOUNT:
+ g_free (self->priv->account);
+ self->priv->account = g_value_dup_string (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec);
+ }
+}
+
+static void
+finalize (GObject *object)
+{
+ ExampleCallableConnection *self = EXAMPLE_CALLABLE_CONNECTION (object);
+
+ tp_contacts_mixin_finalize (object);
+ g_free (self->priv->account);
+ g_free (self->priv->presence_message);
+
+ G_OBJECT_CLASS (example_callable_connection_parent_class)->finalize (object);
+}
+
+static gchar *
+get_unique_connection_name (TpBaseConnection *conn)
+{
+ ExampleCallableConnection *self = EXAMPLE_CALLABLE_CONNECTION (conn);
+
+ return g_strdup_printf ("%s@%p", self->priv->account, self);
+}
+
+gchar *
+example_callable_normalize_contact (TpHandleRepoIface *repo,
+ const gchar *id,
+ gpointer context,
+ GError **error)
+{
+ if (id[0] == '\0')
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_HANDLE,
+ "Contact ID must not be empty");
+ return NULL;
+ }
+
+ return g_utf8_normalize (id, -1, G_NORMALIZE_ALL_COMPOSE);
+}
+
+static void
+create_handle_repos (TpBaseConnection *conn,
+ TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES])
+{
+ repos[TP_HANDLE_TYPE_CONTACT] = tp_dynamic_handle_repo_new
+ (TP_HANDLE_TYPE_CONTACT, example_callable_normalize_contact, NULL);
+}
+
+static GPtrArray *
+create_channel_managers (TpBaseConnection *conn)
+{
+ GPtrArray *ret = g_ptr_array_sized_new (1);
+
+ g_ptr_array_add (ret,
+ g_object_new (EXAMPLE_TYPE_CALLABLE_MEDIA_MANAGER,
+ "connection", conn,
+ NULL));
+
+ return ret;
+}
+
+static gboolean
+start_connecting (TpBaseConnection *conn,
+ GError **error)
+{
+ ExampleCallableConnection *self = EXAMPLE_CALLABLE_CONNECTION (conn);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn,
+ TP_HANDLE_TYPE_CONTACT);
+
+ /* In a real connection manager we'd ask the underlying implementation to
+ * start connecting, then go to state CONNECTED when finished, but here
+ * we can do it immediately. */
+
+ conn->self_handle = tp_handle_ensure (contact_repo, self->priv->account,
+ NULL, error);
+
+ if (conn->self_handle == 0)
+ return FALSE;
+
+ tp_base_connection_change_status (conn, TP_CONNECTION_STATUS_CONNECTED,
+ TP_CONNECTION_STATUS_REASON_REQUESTED);
+
+ return TRUE;
+}
+
+static void
+shut_down (TpBaseConnection *conn)
+{
+ /* In a real connection manager we'd ask the underlying implementation to
+ * start shutting down, then call this function when finished, but here
+ * we can do it immediately. */
+ tp_base_connection_finish_shutdown (conn);
+}
+
+static void
+constructed (GObject *object)
+{
+ TpBaseConnection *base = TP_BASE_CONNECTION (object);
+ void (*chain_up) (GObject *) =
+ G_OBJECT_CLASS (example_callable_connection_parent_class)->constructed;
+
+ if (chain_up != NULL)
+ chain_up (object);
+
+ tp_contacts_mixin_init (object,
+ G_STRUCT_OFFSET (ExampleCallableConnection, contacts_mixin));
+ tp_base_connection_register_with_contacts_mixin (base);
+
+ tp_presence_mixin_init (object,
+ G_STRUCT_OFFSET (ExampleCallableConnection, presence_mixin));
+ tp_presence_mixin_simple_presence_register_with_contacts_mixin (object);
+}
+
+static gboolean
+status_available (GObject *object,
+ guint index_)
+{
+ TpBaseConnection *base = TP_BASE_CONNECTION (object);
+
+ if (base->status != TP_CONNECTION_STATUS_CONNECTED)
+ return FALSE;
+
+ return TRUE;
+}
+
+static GHashTable *
+get_contact_statuses (GObject *object,
+ const GArray *contacts,
+ GError **error)
+{
+ ExampleCallableConnection *self =
+ EXAMPLE_CALLABLE_CONNECTION (object);
+ TpBaseConnection *base = TP_BASE_CONNECTION (object);
+ guint i;
+ GHashTable *result = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) tp_presence_status_free);
+
+ for (i = 0; i < contacts->len; i++)
+ {
+ TpHandle contact = g_array_index (contacts, guint, i);
+ ExampleCallablePresence presence;
+ GHashTable *parameters;
+
+ parameters = g_hash_table_new_full (g_str_hash,
+ g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free);
+
+ /* we know our own status from the connection; for this example CM,
+ * everyone else's status is assumed to be "available" */
+ if (contact == base->self_handle)
+ {
+ presence = (self->priv->away ? EXAMPLE_CALLABLE_PRESENCE_AWAY
+ : EXAMPLE_CALLABLE_PRESENCE_AVAILABLE);
+
+ if (self->priv->presence_message[0] != '\0')
+ g_hash_table_insert (parameters, "message",
+ tp_g_value_slice_new_string (self->priv->presence_message));
+ }
+ else
+ {
+ presence = EXAMPLE_CALLABLE_PRESENCE_AVAILABLE;
+ }
+
+ g_hash_table_insert (result, GUINT_TO_POINTER (contact),
+ tp_presence_status_new (presence, parameters));
+ g_hash_table_destroy (parameters);
+ }
+
+ return result;
+}
+
+static gboolean
+set_own_status (GObject *object,
+ const TpPresenceStatus *status,
+ GError **error)
+{
+ ExampleCallableConnection *self =
+ EXAMPLE_CALLABLE_CONNECTION (object);
+ TpBaseConnection *base = TP_BASE_CONNECTION (object);
+ GHashTable *presences;
+ const gchar *message = "";
+
+ if (status->optional_arguments != NULL)
+ {
+ GValue *v = g_hash_table_lookup (status->optional_arguments, "message");
+
+ if (v != NULL && G_VALUE_HOLDS_STRING (v))
+ {
+ message = g_value_get_string (v);
+
+ if (message == NULL)
+ message = "";
+ }
+ }
+
+ if (status->index == EXAMPLE_CALLABLE_PRESENCE_AWAY)
+ {
+ if (self->priv->away && !tp_strdiff (message,
+ self->priv->presence_message))
+ return TRUE;
+
+ self->priv->away = TRUE;
+ }
+ else
+ {
+ if (!self->priv->away && !tp_strdiff (message,
+ self->priv->presence_message))
+ return TRUE;
+
+ self->priv->away = FALSE;
+ }
+
+ g_free (self->priv->presence_message);
+ self->priv->presence_message = g_strdup (message);
+
+ presences = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, NULL);
+ g_hash_table_insert (presences, GUINT_TO_POINTER (base->self_handle),
+ (gpointer) status);
+ tp_presence_mixin_emit_presence_update (object, presences);
+ g_hash_table_destroy (presences);
+ return TRUE;
+}
+
+static const TpPresenceStatusOptionalArgumentSpec can_have_message[] = {
+ { "message", "s", NULL, NULL },
+ { NULL }
+};
+
+/* Must be kept in sync with ExampleCallablePresence enum in header */
+static const TpPresenceStatusSpec presence_statuses[] = {
+ { "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE, FALSE, NULL },
+ { "unknown", TP_CONNECTION_PRESENCE_TYPE_UNKNOWN, FALSE, NULL },
+ { "error", TP_CONNECTION_PRESENCE_TYPE_ERROR, FALSE, NULL },
+ { "away", TP_CONNECTION_PRESENCE_TYPE_AWAY, TRUE, can_have_message },
+ { "available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE, TRUE,
+ can_have_message },
+ { NULL }
+};
+
+static void
+example_callable_connection_class_init (
+ ExampleCallableConnectionClass *klass)
+{
+ static const gchar *interfaces_always_present[] = {
+ TP_IFACE_CONNECTION_INTERFACE_CONTACTS,
+ TP_IFACE_CONNECTION_INTERFACE_PRESENCE,
+ TP_IFACE_CONNECTION_INTERFACE_REQUESTS,
+ TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE,
+ NULL };
+ TpBaseConnectionClass *base_class = (TpBaseConnectionClass *) klass;
+ GObjectClass *object_class = (GObjectClass *) klass;
+ GParamSpec *param_spec;
+
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->constructed = constructed;
+ object_class->finalize = finalize;
+ g_type_class_add_private (klass,
+ sizeof (ExampleCallableConnectionPrivate));
+
+ base_class->create_handle_repos = create_handle_repos;
+ base_class->get_unique_connection_name = get_unique_connection_name;
+ base_class->create_channel_managers = create_channel_managers;
+ base_class->start_connecting = start_connecting;
+ base_class->shut_down = shut_down;
+ base_class->interfaces_always_present = interfaces_always_present;
+
+ param_spec = g_param_spec_string ("account", "Account name",
+ "The username of this user", NULL,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_ACCOUNT, param_spec);
+
+ tp_contacts_mixin_class_init (object_class,
+ G_STRUCT_OFFSET (ExampleCallableConnectionClass, contacts_mixin));
+ tp_presence_mixin_class_init (object_class,
+ G_STRUCT_OFFSET (ExampleCallableConnectionClass, presence_mixin),
+ status_available, get_contact_statuses, set_own_status,
+ presence_statuses);
+ tp_presence_mixin_simple_presence_init_dbus_properties (object_class);
+}
diff --git a/examples/cm/callable/conn.h b/examples/cm/callable/conn.h
new file mode 100644
index 0000000..f3d4690
--- /dev/null
+++ b/examples/cm/callable/conn.h
@@ -0,0 +1,78 @@
+/*
+ * conn.h - header for an example connection
+ *
+ * Copyright © 2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright © 2007-2009 Nokia Corporation
+ *
+ * Copying and distribution of this file, with or without modification,
+ * are permitted in any medium without royalty provided the copyright
+ * notice and this notice are preserved.
+ */
+
+#ifndef __EXAMPLE_CALLABLE_CONN_H__
+#define __EXAMPLE_CALLABLE_CONN_H__
+
+#include <glib-object.h>
+#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/contacts-mixin.h>
+#include <telepathy-glib/presence-mixin.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ExampleCallableConnection ExampleCallableConnection;
+typedef struct _ExampleCallableConnectionPrivate
+ ExampleCallableConnectionPrivate;
+
+typedef struct _ExampleCallableConnectionClass ExampleCallableConnectionClass;
+typedef struct _ExampleCallableConnectionClassPrivate
+ ExampleCallableConnectionClassPrivate;
+
+struct _ExampleCallableConnectionClass {
+ TpBaseConnectionClass parent_class;
+ TpPresenceMixinClass presence_mixin;
+ TpContactsMixinClass contacts_mixin;
+
+ ExampleCallableConnectionClassPrivate *priv;
+};
+
+struct _ExampleCallableConnection {
+ TpBaseConnection parent;
+ TpPresenceMixin presence_mixin;
+ TpContactsMixin contacts_mixin;
+
+ ExampleCallableConnectionPrivate *priv;
+};
+
+GType example_callable_connection_get_type (void);
+
+#define EXAMPLE_TYPE_CALLABLE_CONNECTION \
+ (example_callable_connection_get_type ())
+#define EXAMPLE_CALLABLE_CONNECTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), EXAMPLE_TYPE_CALLABLE_CONNECTION, \
+ ExampleCallableConnection))
+#define EXAMPLE_CALLABLE_CONNECTION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), EXAMPLE_TYPE_CALLABLE_CONNECTION, \
+ ExampleCallableConnectionClass))
+#define EXAMPLE_IS_CALLABLE_CONNECTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), EXAMPLE_TYPE_CALLABLE_CONNECTION))
+#define EXAMPLE_IS_CALLABLE_CONNECTION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), EXAMPLE_TYPE_CALLABLE_CONNECTION))
+#define EXAMPLE_CALLABLE_CONNECTION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), EXAMPLE_TYPE_CALLABLE_CONNECTION, \
+ ExampleCallableConnectionClass))
+
+gchar *example_callable_normalize_contact (TpHandleRepoIface *repo,
+ const gchar *id, gpointer context, GError **error);
+
+/* Must be kept in sync with the array presence_statuses in conn.c */
+typedef enum {
+ EXAMPLE_CALLABLE_PRESENCE_OFFLINE = 0,
+ EXAMPLE_CALLABLE_PRESENCE_UNKNOWN,
+ EXAMPLE_CALLABLE_PRESENCE_ERROR,
+ EXAMPLE_CALLABLE_PRESENCE_AWAY,
+ EXAMPLE_CALLABLE_PRESENCE_AVAILABLE
+} ExampleCallablePresence;
+
+G_END_DECLS
+
+#endif
diff --git a/examples/cm/callable/connection-manager.c b/examples/cm/callable/connection-manager.c
new file mode 100644
index 0000000..768cc1c
--- /dev/null
+++ b/examples/cm/callable/connection-manager.c
@@ -0,0 +1,125 @@
+/*
+ * manager.c - an example connection manager
+ *
+ * Copyright © 2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright © 2007-2009 Nokia Corporation
+ *
+ * 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 "connection-manager.h"
+
+#include <dbus/dbus-glib.h>
+
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/errors.h>
+
+#include "conn.h"
+
+G_DEFINE_TYPE (ExampleCallableConnectionManager,
+ example_callable_connection_manager,
+ TP_TYPE_BASE_CONNECTION_MANAGER)
+
+struct _ExampleCallableConnectionManagerPrivate
+{
+ int dummy;
+};
+
+static void
+example_callable_connection_manager_init (
+ ExampleCallableConnectionManager *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ EXAMPLE_TYPE_CALLABLE_CONNECTION_MANAGER,
+ ExampleCallableConnectionManagerPrivate);
+}
+
+typedef struct {
+ gchar *account;
+} ExampleParams;
+
+static gboolean
+account_param_filter (const TpCMParamSpec *paramspec,
+ GValue *value,
+ GError **error)
+{
+ const gchar *id = g_value_get_string (value);
+
+ g_value_take_string (value,
+ example_callable_normalize_contact (NULL, id, NULL, error));
+
+ if (g_value_get_string (value) == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+#include "_gen/param-spec-struct.h"
+
+static gpointer
+alloc_params (void)
+{
+ return g_slice_new0 (ExampleParams);
+}
+
+static void
+free_params (gpointer p)
+{
+ ExampleParams *params = p;
+
+ g_free (params->account);
+
+ g_slice_free (ExampleParams, params);
+}
+
+static const TpCMProtocolSpec example_protocols[] = {
+ { "example", example_callable_example_params,
+ alloc_params, free_params },
+ { NULL, NULL }
+};
+
+static TpBaseConnection *
+new_connection (TpBaseConnectionManager *self,
+ const gchar *proto,
+ TpIntSet *params_present,
+ gpointer parsed_params,
+ GError **error)
+{
+ ExampleParams *params = parsed_params;
+ ExampleCallableConnection *conn;
+
+ conn = EXAMPLE_CALLABLE_CONNECTION
+ (g_object_new (EXAMPLE_TYPE_CALLABLE_CONNECTION,
+ "account", params->account,
+ "protocol", proto,
+ NULL));
+
+ return (TpBaseConnection *) conn;
+}
+
+static void
+example_callable_connection_manager_class_init (
+ ExampleCallableConnectionManagerClass *klass)
+{
+ TpBaseConnectionManagerClass *base_class =
+ (TpBaseConnectionManagerClass *) klass;
+
+ g_type_class_add_private (klass,
+ sizeof (ExampleCallableConnectionManagerPrivate));
+
+ base_class->new_connection = new_connection;
+ base_class->cm_dbus_name = "example_callable";
+ base_class->protocol_params = example_protocols;
+}
diff --git a/examples/cm/callable/connection-manager.h b/examples/cm/callable/connection-manager.h
new file mode 100644
index 0000000..5d854cb
--- /dev/null
+++ b/examples/cm/callable/connection-manager.h
@@ -0,0 +1,73 @@
+/*
+ * manager.h - header for an example connection manager
+ *
+ * Copyright © 2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright © 2007-2009 Nokia Corporation
+ *
+ * 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 __EXAMPLE_CALLABLE_CONNECTION_MANAGER_H__
+#define __EXAMPLE_CALLABLE_CONNECTION_MANAGER_H__
+
+#include <glib-object.h>
+#include <telepathy-glib/base-connection-manager.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ExampleCallableConnectionManager
+ ExampleCallableConnectionManager;
+typedef struct _ExampleCallableConnectionManagerPrivate
+ ExampleCallableConnectionManagerPrivate;
+
+typedef struct _ExampleCallableConnectionManagerClass
+ ExampleCallableConnectionManagerClass;
+typedef struct _ExampleCallableConnectionManagerClassPrivate
+ ExampleCallableConnectionManagerClassPrivate;
+
+struct _ExampleCallableConnectionManagerClass {
+ TpBaseConnectionManagerClass parent_class;
+
+ ExampleCallableConnectionManagerClassPrivate *priv;
+};
+
+struct _ExampleCallableConnectionManager {
+ TpBaseConnectionManager parent;
+
+ ExampleCallableConnectionManagerPrivate *priv;
+};
+
+GType example_callable_connection_manager_get_type (void);
+
+/* TYPE MACROS */
+#define EXAMPLE_TYPE_CALLABLE_CONNECTION_MANAGER \
+ (example_callable_connection_manager_get_type ())
+#define EXAMPLE_CALLABLE_CONNECTION_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), EXAMPLE_TYPE_CALLABLE_CONNECTION_MANAGER, \
+ ExampleCallableConnectionManager))
+#define EXAMPLE_CALLABLE_CONNECTION_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), EXAMPLE_TYPE_CALLABLE_CONNECTION_MANAGER, \
+ ExampleCallableConnectionManagerClass))
+#define EXAMPLE_IS_CALLABLE_CONNECTION_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), EXAMPLE_TYPE_CALLABLE_CONNECTION_MANAGER))
+#define EXAMPLE_IS_CALLABLE_CONNECTION_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), EXAMPLE_TYPE_CALLABLE_CONNECTION_MANAGER))
+#define EXAMPLE_CALLABLE_CONNECTION_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), EXAMPLE_TYPE_CALLABLE_CONNECTION_MANAGER, \
+ ExampleCallableConnectionManagerClass))
+
+G_END_DECLS
+
+#endif
diff --git a/examples/cm/callable/main.c b/examples/cm/callable/main.c
new file mode 100644
index 0000000..ea0b171
--- /dev/null
+++ b/examples/cm/callable/main.c
@@ -0,0 +1,54 @@
+/*
+ * main.c - entry point for an example Telepathy connection manager
+ *
+ * Copyright © 2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright © 2007-2009 Nokia Corporation
+ *
+ * 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/debug.h>
+#include <telepathy-glib/run.h>
+
+#include "connection-manager.h"
+
+static TpBaseConnectionManager *
+construct_cm (void)
+{
+ return (TpBaseConnectionManager *) g_object_new (
+ EXAMPLE_TYPE_CALLABLE_CONNECTION_MANAGER,
+ NULL);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+#ifdef ENABLE_DEBUG
+ tp_debug_divert_messages (g_getenv ("EXAMPLE_CM_LOGFILE"));
+ tp_debug_set_flags (g_getenv ("EXAMPLE_DEBUG"));
+
+ if (g_getenv ("EXAMPLE_TIMING") != NULL)
+ g_log_set_default_handler (tp_debug_timestamped_log_handler, NULL);
+
+ if (g_getenv ("EXAMPLE_PERSIST") != NULL)
+ tp_debug_set_persistent (TRUE);
+#endif
+
+ return tp_run_connection_manager ("telepathy-example-cm-callable",
+ VERSION, construct_cm, argc, argv);
+}
diff --git a/examples/cm/callable/manager-file.py b/examples/cm/callable/manager-file.py
new file mode 100644
index 0000000..6811e3d
--- /dev/null
+++ b/examples/cm/callable/manager-file.py
@@ -0,0 +1,19 @@
+# Input for tools/manager-file.py
+
+MANAGER = 'example_callable'
+PARAMS = {
+ 'example' : {
+ 'account': {
+ 'dtype': 's',
+ 'flags': 'required register',
+ 'filter': 'account_param_filter',
+ # 'filter_data': 'NULL',
+ # 'default': ...,
+ # 'struct_field': '...',
+ # 'setter_data': 'NULL',
+ },
+ },
+ }
+STRUCTS = {
+ 'example': 'ExampleParams'
+ }
diff --git a/examples/cm/callable/media-channel.c b/examples/cm/callable/media-channel.c
new file mode 100644
index 0000000..5e13b3c
--- /dev/null
+++ b/examples/cm/callable/media-channel.c
@@ -0,0 +1,546 @@
+/*
+ * media-channel.c - an example 1-1 streamed media call.
+ *
+ * For simplicity, this channel emulates a device with its own
+ * audio/video user interface, like a video-equipped form of the phones
+ * manipulated by telepathy-snom or gnome-phone-manager.
+ *
+ * As a result, this channel does not have the MediaSignalling interface, and
+ * clients should not attempt to do their own streaming using
+ * telepathy-farsight, telepathy-stream-engine or maemo-stream-engine.
+ *
+ * In practice, nearly all connection managers also have the MediaSignalling
+ * interface on their streamed media channels. Usage for those CMs is the
+ * same, except that whichever client is the primary handler for the channel
+ * should also hand the channel over to telepathy-farsight or
+ * telepathy-stream-engine to implement the actual streaming.
+ *
+ * Copyright © 2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright © 2007-2009 Nokia Corporation
+ *
+ * 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 "media-channel.h"
+
+#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/channel-iface.h>
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/svc-channel.h>
+#include <telepathy-glib/svc-generic.h>
+
+static void media_iface_init (gpointer iface, gpointer data);
+static void channel_iface_init (gpointer iface, gpointer data);
+
+G_DEFINE_TYPE_WITH_CODE (ExampleCallableMediaChannel,
+ example_callable_media_channel,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
+ tp_dbus_properties_mixin_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_STREAMED_MEDIA,
+ media_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP,
+ tp_group_mixin_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL))
+
+enum
+{
+ PROP_OBJECT_PATH = 1,
+ PROP_CHANNEL_TYPE,
+ PROP_HANDLE_TYPE,
+ PROP_HANDLE,
+ PROP_TARGET_ID,
+ PROP_REQUESTED,
+ PROP_INITIATOR_HANDLE,
+ PROP_INITIATOR_ID,
+ PROP_CONNECTION,
+ PROP_INTERFACES,
+ PROP_CHANNEL_DESTROYED,
+ PROP_CHANNEL_PROPERTIES,
+ N_PROPS
+};
+
+struct _ExampleCallableMediaChannelPrivate
+{
+ TpBaseConnection *conn;
+ gchar *object_path;
+ TpHandle handle;
+ TpHandle initiator;
+
+ /* These are really booleans, but gboolean is signed. Thanks, GLib */
+ unsigned closed:1;
+ unsigned disposed:1;
+};
+
+static const char * example_callable_media_channel_interfaces[] = {
+ TP_IFACE_CHANNEL_INTERFACE_GROUP,
+ NULL
+};
+
+static void
+example_callable_media_channel_init (ExampleCallableMediaChannel *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ EXAMPLE_TYPE_CALLABLE_MEDIA_CHANNEL,
+ ExampleCallableMediaChannelPrivate);
+}
+
+static void
+constructed (GObject *object)
+{
+ void (*chain_up) (GObject *) =
+ ((GObjectClass *) example_callable_media_channel_parent_class)->constructed;
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (object);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
+ (self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+ DBusGConnection *bus;
+
+ if (chain_up != NULL)
+ chain_up (object);
+
+ tp_handle_ref (contact_repo, self->priv->handle);
+ tp_handle_ref (contact_repo, self->priv->initiator);
+
+ bus = tp_get_bus ();
+ dbus_g_connection_register_g_object (bus, self->priv->object_path, object);
+
+ tp_group_mixin_init (object,
+ G_STRUCT_OFFSET (ExampleCallableMediaChannel, group),
+ contact_repo, self->priv->conn->self_handle);
+
+ /* FIXME: correct flags */
+ tp_group_mixin_change_flags (object,
+ TP_CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES |
+ TP_CHANNEL_GROUP_FLAG_PROPERTIES,
+ 0);
+}
+
+static void
+get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (object);
+
+ switch (property_id)
+ {
+ case PROP_OBJECT_PATH:
+ g_value_set_string (value, self->priv->object_path);
+ break;
+
+ case PROP_CHANNEL_TYPE:
+ g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA);
+ break;
+
+ case PROP_HANDLE_TYPE:
+ g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
+ break;
+
+ case PROP_HANDLE:
+ g_value_set_uint (value, self->priv->handle);
+ break;
+
+ case PROP_TARGET_ID:
+ {
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+
+ g_value_set_string (value,
+ tp_handle_inspect (contact_repo, self->priv->handle));
+ }
+ break;
+
+ case PROP_REQUESTED:
+ g_value_set_boolean (value,
+ (self->priv->initiator == self->priv->conn->self_handle));
+ break;
+
+ case PROP_INITIATOR_HANDLE:
+ g_value_set_uint (value, self->priv->initiator);
+ break;
+
+ case PROP_INITIATOR_ID:
+ {
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+
+ g_value_set_string (value,
+ tp_handle_inspect (contact_repo, self->priv->initiator));
+ }
+ break;
+
+ case PROP_CONNECTION:
+ g_value_set_object (value, self->priv->conn);
+ break;
+
+ case PROP_INTERFACES:
+ g_value_set_boxed (value, example_callable_media_channel_interfaces);
+ break;
+
+ case PROP_CHANNEL_DESTROYED:
+ g_value_set_boolean (value, self->priv->closed);
+ break;
+
+ case PROP_CHANNEL_PROPERTIES:
+ g_value_take_boxed (value,
+ tp_dbus_properties_mixin_make_properties_hash (object,
+ TP_IFACE_CHANNEL, "ChannelType",
+ TP_IFACE_CHANNEL, "TargetHandleType",
+ TP_IFACE_CHANNEL, "TargetHandle",
+ TP_IFACE_CHANNEL, "TargetID",
+ TP_IFACE_CHANNEL, "InitiatorHandle",
+ TP_IFACE_CHANNEL, "InitiatorID",
+ TP_IFACE_CHANNEL, "Requested",
+ TP_IFACE_CHANNEL, "Interfaces",
+ NULL));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (object);
+
+ switch (property_id)
+ {
+ case PROP_OBJECT_PATH:
+ g_assert (self->priv->object_path == NULL);
+ self->priv->object_path = g_value_dup_string (value);
+ break;
+
+ case PROP_HANDLE:
+ /* we don't ref it here because we don't necessarily have access to the
+ * contact repo yet - instead we ref it in the constructor.
+ */
+ self->priv->handle = g_value_get_uint (value);
+ break;
+
+ case PROP_INITIATOR_HANDLE:
+ /* likewise */
+ self->priv->initiator = g_value_get_uint (value);
+ break;
+
+ case PROP_HANDLE_TYPE:
+ case PROP_CHANNEL_TYPE:
+ /* these properties are writable in the interface, but not actually
+ * meaningfully changable on this channel, so we do nothing */
+ break;
+
+ case PROP_CONNECTION:
+ self->priv->conn = g_value_get_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+example_callable_media_channel_close (ExampleCallableMediaChannel *self)
+{
+ if (!self->priv->closed)
+ {
+ self->priv->closed = TRUE;
+ tp_svc_channel_emit_closed (self);
+ }
+}
+
+static void
+dispose (GObject *object)
+{
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (object);
+
+ if (self->priv->disposed)
+ return;
+
+ self->priv->disposed = TRUE;
+
+ example_callable_media_channel_close (self);
+
+ ((GObjectClass *) example_callable_media_channel_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (object);
+ TpHandleRepoIface *contact_handles = tp_base_connection_get_handles
+ (self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+
+ tp_handle_unref (contact_handles, self->priv->handle);
+ tp_handle_unref (contact_handles, self->priv->initiator);
+
+ g_free (self->priv->object_path);
+
+ tp_group_mixin_finalize (object);
+
+ ((GObjectClass *) example_callable_media_channel_parent_class)->finalize (object);
+}
+
+static gboolean
+add_member (GObject *object,
+ TpHandle member,
+ const gchar *message,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+remove_member_with_reason (GObject *object,
+ TpHandle member,
+ const gchar *message,
+ guint reason,
+ GError **error)
+{
+ return TRUE;
+}
+
+static void
+example_callable_media_channel_class_init (ExampleCallableMediaChannelClass *klass)
+{
+ static TpDBusPropertiesMixinPropImpl channel_props[] = {
+ { "TargetHandleType", "handle-type", NULL },
+ { "TargetHandle", "handle", NULL },
+ { "ChannelType", "channel-type", NULL },
+ { "Interfaces", "interfaces", NULL },
+ { "TargetID", "target-id", NULL },
+ { "Requested", "requested", NULL },
+ { "InitiatorHandle", "initiator-handle", NULL },
+ { "InitiatorID", "initiator-id", NULL },
+ { NULL }
+ };
+ static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
+ { TP_IFACE_CHANNEL,
+ tp_dbus_properties_mixin_getter_gobject_properties,
+ NULL,
+ channel_props,
+ },
+ { NULL }
+ };
+ GObjectClass *object_class = (GObjectClass *) klass;
+ GParamSpec *param_spec;
+
+ g_type_class_add_private (klass,
+ sizeof (ExampleCallableMediaChannelPrivate));
+
+ object_class->constructed = constructed;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->dispose = dispose;
+ object_class->finalize = finalize;
+
+ g_object_class_override_property (object_class, PROP_OBJECT_PATH,
+ "object-path");
+ g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
+ "channel-type");
+ g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
+ "handle-type");
+ g_object_class_override_property (object_class, PROP_HANDLE, "handle");
+
+ g_object_class_override_property (object_class, PROP_CHANNEL_DESTROYED,
+ "channel-destroyed");
+ g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES,
+ "channel-properties");
+
+ param_spec = g_param_spec_object ("connection", "TpBaseConnection object",
+ "Connection object that owns this channel",
+ TP_TYPE_BASE_CONNECTION,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
+
+ param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
+ "Additional Channel.Interface.* interfaces",
+ G_TYPE_STRV,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
+
+ param_spec = g_param_spec_string ("target-id", "Peer's ID",
+ "The string obtained by inspecting the target handle",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec);
+
+ param_spec = g_param_spec_uint ("initiator-handle", "Initiator's handle",
+ "The contact who initiated the channel",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_INITIATOR_HANDLE,
+ param_spec);
+
+ param_spec = g_param_spec_string ("initiator-id", "Initiator's ID",
+ "The string obtained by inspecting the initiator-handle",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_INITIATOR_ID,
+ param_spec);
+
+ param_spec = g_param_spec_boolean ("requested", "Requested?",
+ "True if this channel was requested by the local user",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_REQUESTED, param_spec);
+
+ klass->dbus_properties_class.interfaces = prop_interfaces;
+ tp_dbus_properties_mixin_class_init (object_class,
+ G_STRUCT_OFFSET (ExampleCallableMediaChannelClass,
+ dbus_properties_class));
+
+ tp_group_mixin_class_init (object_class,
+ G_STRUCT_OFFSET (ExampleCallableMediaChannelClass, group_class),
+ add_member,
+ NULL);
+ tp_group_mixin_class_set_remove_with_reason_func (object_class,
+ remove_member_with_reason);
+ tp_group_mixin_init_dbus_properties (object_class);
+}
+
+static void
+channel_close (TpSvcChannel *iface,
+ DBusGMethodInvocation *context)
+{
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
+
+ example_callable_media_channel_close (self);
+ tp_svc_channel_return_from_close (context);
+}
+
+static void
+channel_get_channel_type (TpSvcChannel *iface G_GNUC_UNUSED,
+ DBusGMethodInvocation *context)
+{
+ tp_svc_channel_return_from_get_channel_type (context,
+ TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA);
+}
+
+static void
+channel_get_handle (TpSvcChannel *iface,
+ DBusGMethodInvocation *context)
+{
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
+
+ tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_CONTACT,
+ self->priv->handle);
+}
+
+static void
+channel_get_interfaces (TpSvcChannel *iface G_GNUC_UNUSED,
+ DBusGMethodInvocation *context)
+{
+ tp_svc_channel_return_from_get_interfaces (context,
+ example_callable_media_channel_interfaces);
+}
+
+static void
+channel_iface_init (gpointer iface,
+ gpointer data)
+{
+ TpSvcChannelClass *klass = iface;
+
+#define IMPLEMENT(x) tp_svc_channel_implement_##x (klass, channel_##x)
+ IMPLEMENT (close);
+ IMPLEMENT (get_channel_type);
+ IMPLEMENT (get_handle);
+ IMPLEMENT (get_interfaces);
+#undef IMPLEMENT
+}
+
+static void
+media_list_streams (TpSvcChannelTypeStreamedMedia *iface,
+ DBusGMethodInvocation *context)
+{
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
+ GPtrArray *array = g_ptr_array_sized_new (0);
+
+ /* FIXME */
+ (void) self;
+
+ tp_svc_channel_type_streamed_media_return_from_list_streams (context,
+ array);
+ g_ptr_array_free (array, TRUE);
+}
+
+static void
+media_remove_streams (TpSvcChannelTypeStreamedMedia *iface,
+ const GArray *stream_ids,
+ DBusGMethodInvocation *context)
+{
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
+
+ /* FIXME */
+ (void) self;
+
+ tp_svc_channel_type_streamed_media_return_from_remove_streams (context);
+}
+
+static void
+media_request_stream_direction (TpSvcChannelTypeStreamedMedia *iface,
+ guint stream_id,
+ guint stream_direction,
+ DBusGMethodInvocation *context)
+{
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
+
+ /* FIXME */
+ (void) self;
+
+ tp_svc_channel_type_streamed_media_return_from_request_stream_direction (
+ context);
+}
+
+static void
+media_request_streams (TpSvcChannelTypeStreamedMedia *iface,
+ guint contact_handle,
+ const GArray *media_types,
+ DBusGMethodInvocation *context)
+{
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
+ GPtrArray *array = g_ptr_array_sized_new (0);
+
+ /* FIXME */
+ (void) self;
+
+ tp_svc_channel_type_streamed_media_return_from_request_streams (context,
+ array);
+ g_ptr_array_free (array, TRUE);
+}
+
+static void
+media_iface_init (gpointer iface,
+ gpointer data)
+{
+ TpSvcChannelTypeStreamedMediaClass *klass = iface;
+
+#define IMPLEMENT(x) \
+ tp_svc_channel_type_streamed_media_implement_##x (klass, media_##x)
+ IMPLEMENT (list_streams);
+ IMPLEMENT (remove_streams);
+ IMPLEMENT (request_stream_direction);
+ IMPLEMENT (request_streams);
+#undef IMPLEMENT
+}
diff --git a/examples/cm/callable/media-channel.h b/examples/cm/callable/media-channel.h
new file mode 100644
index 0000000..428370d
--- /dev/null
+++ b/examples/cm/callable/media-channel.h
@@ -0,0 +1,74 @@
+/*
+ * media-channel.h - header for an example channel
+ *
+ * Copyright © 2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright © 2007-2009 Nokia Corporation
+ *
+ * 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 __EXAMPLE_CALLABLE_MEDIA_CHANNEL_H__
+#define __EXAMPLE_CALLABLE_MEDIA_CHANNEL_H__
+
+#include <glib-object.h>
+#include <telepathy-glib/group-mixin.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ExampleCallableMediaChannel ExampleCallableMediaChannel;
+typedef struct _ExampleCallableMediaChannelPrivate
+ ExampleCallableMediaChannelPrivate;
+
+typedef struct _ExampleCallableMediaChannelClass
+ ExampleCallableMediaChannelClass;
+typedef struct _ExampleCallableMediaChannelClassPrivate
+ ExampleCallableMediaChannelClassPrivate;
+
+GType example_callable_media_channel_get_type (void);
+
+#define EXAMPLE_TYPE_CALLABLE_MEDIA_CHANNEL \
+ (example_callable_media_channel_get_type ())
+#define EXAMPLE_CALLABLE_MEDIA_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXAMPLE_TYPE_CALLABLE_MEDIA_CHANNEL, \
+ ExampleCallableMediaChannel))
+#define EXAMPLE_CALLABLE_MEDIA_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), EXAMPLE_TYPE_CALLABLE_MEDIA_CHANNEL, \
+ ExampleCallableMediaChannelClass))
+#define EXAMPLE_IS_CALLABLE_MEDIA_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXAMPLE_TYPE_CALLABLE_MEDIA_CHANNEL))
+#define EXAMPLE_IS_CALLABLE_MEDIA_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), EXAMPLE_TYPE_CALLABLE_MEDIA_CHANNEL))
+#define EXAMPLE_CALLABLE_MEDIA_CHANNEL_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), EXAMPLE_TYPE_CALLABLE_MEDIA_CHANNEL, \
+ ExampleCallableMediaChannelClass))
+
+struct _ExampleCallableMediaChannelClass {
+ GObjectClass parent_class;
+ TpGroupMixinClass group_class;
+ TpDBusPropertiesMixinClass dbus_properties_class;
+
+ ExampleCallableMediaChannelClassPrivate *priv;
+};
+
+struct _ExampleCallableMediaChannel {
+ GObject parent;
+ TpGroupMixin group;
+
+ ExampleCallableMediaChannelPrivate *priv;
+};
+
+G_END_DECLS
+
+#endif
diff --git a/examples/cm/callable/media-manager.c b/examples/cm/callable/media-manager.c
new file mode 100644
index 0000000..453bb47
--- /dev/null
+++ b/examples/cm/callable/media-manager.c
@@ -0,0 +1,400 @@
+/*
+ * media-manager.c - an example channel manager for StreamedMedia calls.
+ * This channel manager emulates a protocol like XMPP Jingle, where you can
+ * make several simultaneous calls to the same or different contacts.
+ *
+ * Copyright © 2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright © 2007-2009 Nokia Corporation
+ *
+ * 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 "media-manager.h"
+
+#include <dbus/dbus-glib.h>
+
+#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/channel-manager.h>
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/errors.h>
+#include <telepathy-glib/interfaces.h>
+
+#include "media-channel.h"
+
+static void channel_manager_iface_init (gpointer, gpointer);
+
+G_DEFINE_TYPE_WITH_CODE (ExampleCallableMediaManager,
+ example_callable_media_manager,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER,
+ channel_manager_iface_init))
+
+/* type definition stuff */
+
+enum
+{
+ PROP_CONNECTION = 1,
+ N_PROPS
+};
+
+struct _ExampleCallableMediaManagerPrivate
+{
+ TpBaseConnection *conn;
+
+ /* List of ExampleCallableMediaChannel */
+ GList *channels;
+
+ /* Next channel will be ("MediaChannel%u", next_channel_index) */
+ guint next_channel_index;
+
+ gulong status_changed_id;
+};
+
+static void
+example_callable_media_manager_init (ExampleCallableMediaManager *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ EXAMPLE_TYPE_CALLABLE_MEDIA_MANAGER,
+ ExampleCallableMediaManagerPrivate);
+
+ self->priv->conn = NULL;
+ self->priv->channels = NULL;
+ self->priv->status_changed_id = 0;
+}
+
+static void
+example_callable_media_manager_close_all (ExampleCallableMediaManager *self)
+{
+ if (self->priv->channels != NULL)
+ {
+ GList *tmp = self->priv->channels;
+
+ self->priv->channels = NULL;
+
+ g_list_foreach (tmp, (GFunc) g_object_unref, NULL);
+ g_list_free (tmp);
+ }
+
+ if (self->priv->status_changed_id != 0)
+ {
+ g_signal_handler_disconnect (self->priv->conn,
+ self->priv->status_changed_id);
+ self->priv->status_changed_id = 0;
+ }
+}
+
+static void
+dispose (GObject *object)
+{
+ ExampleCallableMediaManager *self = EXAMPLE_CALLABLE_MEDIA_MANAGER (object);
+
+ example_callable_media_manager_close_all (self);
+ g_assert (self->priv->channels == NULL);
+
+ ((GObjectClass *) example_callable_media_manager_parent_class)->dispose (
+ object);
+}
+
+static void
+get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ExampleCallableMediaManager *self = EXAMPLE_CALLABLE_MEDIA_MANAGER (object);
+
+ switch (property_id)
+ {
+ case PROP_CONNECTION:
+ g_value_set_object (value, self->priv->conn);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ExampleCallableMediaManager *self = EXAMPLE_CALLABLE_MEDIA_MANAGER (object);
+
+ switch (property_id)
+ {
+ case PROP_CONNECTION:
+ /* We don't ref the connection, because it owns a reference to the
+ * channel manager, and it guarantees that the manager's lifetime is
+ * less than its lifetime */
+ self->priv->conn = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+status_changed_cb (TpBaseConnection *conn,
+ guint status,
+ guint reason,
+ ExampleCallableMediaManager *self)
+{
+ switch (status)
+ {
+ case TP_CONNECTION_STATUS_DISCONNECTED:
+ {
+ example_callable_media_manager_close_all (self);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+constructed (GObject *object)
+{
+ ExampleCallableMediaManager *self = EXAMPLE_CALLABLE_MEDIA_MANAGER (object);
+ void (*chain_up) (GObject *) =
+ ((GObjectClass *) example_callable_media_manager_parent_class)->constructed;
+
+ if (chain_up != NULL)
+ {
+ chain_up (object);
+ }
+
+ self->priv->status_changed_id = g_signal_connect (self->priv->conn,
+ "status-changed", (GCallback) status_changed_cb, self);
+}
+
+static void
+example_callable_media_manager_class_init (
+ ExampleCallableMediaManagerClass *klass)
+{
+ GParamSpec *param_spec;
+ GObjectClass *object_class = (GObjectClass *) klass;
+
+ object_class->constructed = constructed;
+ object_class->dispose = dispose;
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+
+ param_spec = g_param_spec_object ("connection", "Connection object",
+ "The connection that owns this channel manager",
+ TP_TYPE_BASE_CONNECTION,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
+
+ g_type_class_add_private (klass,
+ sizeof (ExampleCallableMediaManagerPrivate));
+}
+
+static void
+example_callable_media_manager_foreach_channel (
+ TpChannelManager *iface,
+ TpExportableChannelFunc callback,
+ gpointer user_data)
+{
+ ExampleCallableMediaManager *self = EXAMPLE_CALLABLE_MEDIA_MANAGER (iface);
+
+ g_list_foreach (self->priv->channels, (GFunc) callback, user_data);
+}
+
+static void
+channel_closed_cb (ExampleCallableMediaChannel *chan,
+ ExampleCallableMediaManager *self)
+{
+ tp_channel_manager_emit_channel_closed_for_object (self,
+ TP_EXPORTABLE_CHANNEL (chan));
+
+ if (self->priv->channels != NULL)
+ {
+ self->priv->channels = g_list_remove_all (self->priv->channels, chan);
+ }
+}
+
+static ExampleCallableMediaChannel *
+new_channel (ExampleCallableMediaManager *self,
+ TpHandle handle,
+ TpHandle initiator,
+ gpointer request_token)
+{
+ ExampleCallableMediaChannel *chan;
+ gchar *object_path;
+ GSList *requests = NULL;
+
+ /* FIXME: This could potentially wrap around, but only after 4 billion
+ * calls, which is probably plenty. */
+ object_path = g_strdup_printf ("%s/MediaChannel%u",
+ self->priv->conn->object_path, self->priv->next_channel_index++);
+
+ chan = g_object_new (EXAMPLE_TYPE_CALLABLE_MEDIA_CHANNEL,
+ "connection", self->priv->conn,
+ "object-path", object_path,
+ "handle", handle,
+ "initiator-handle", initiator,
+ NULL);
+
+ g_free (object_path);
+
+ g_signal_connect (chan, "closed", G_CALLBACK (channel_closed_cb), self);
+
+ self->priv->channels = g_list_prepend (self->priv->channels, chan);
+
+ if (request_token != NULL)
+ requests = g_slist_prepend (requests, request_token);
+
+ tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (chan),
+ requests);
+ g_slist_free (requests);
+
+ return chan;
+}
+
+static const gchar * const fixed_properties[] = {
+ TP_IFACE_CHANNEL ".ChannelType",
+ TP_IFACE_CHANNEL ".TargetHandleType",
+ NULL
+};
+
+static const gchar * const allowed_properties[] = {
+ TP_IFACE_CHANNEL ".TargetHandle",
+ TP_IFACE_CHANNEL ".TargetID",
+ NULL
+};
+
+static void
+example_callable_media_manager_foreach_channel_class (
+ TpChannelManager *manager,
+ TpChannelManagerChannelClassFunc func,
+ gpointer user_data)
+{
+ GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) tp_g_value_slice_free);
+
+ g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType",
+ tp_g_value_slice_new_static_string (
+ TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA));
+
+ g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType",
+ tp_g_value_slice_new_uint (TP_HANDLE_TYPE_CONTACT));
+
+ func (manager, table, allowed_properties, user_data);
+
+ g_hash_table_destroy (table);
+}
+
+static gboolean
+example_callable_media_manager_request (ExampleCallableMediaManager *self,
+ gpointer request_token,
+ GHashTable *request_properties,
+ gboolean require_new)
+{
+ TpHandle handle;
+ GError *error = NULL;
+
+ if (tp_strdiff (tp_asv_get_string (request_properties,
+ TP_IFACE_CHANNEL ".ChannelType"),
+ TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA))
+ {
+ return FALSE;
+ }
+
+ if (tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT)
+ {
+ return FALSE;
+ }
+
+ handle = tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandle", NULL);
+ g_assert (handle != 0);
+
+ if (tp_channel_manager_asv_has_unknown_properties (request_properties,
+ fixed_properties, allowed_properties, &error))
+ {
+ goto error;
+ }
+
+ if (!require_new)
+ {
+ /* see if we're already calling that handle */
+ const GList *link;
+
+ for (link = self->priv->channels; link != NULL; link = link->next)
+ {
+ guint its_handle;
+
+ g_object_get (link->data,
+ "handle", &its_handle,
+ NULL);
+
+ if (its_handle == handle)
+ {
+ tp_channel_manager_emit_request_already_satisfied (self,
+ request_token, TP_EXPORTABLE_CHANNEL (link->data));
+ return TRUE;
+ }
+ }
+ }
+
+ new_channel (self, handle, self->priv->conn->self_handle,
+ request_token);
+ return TRUE;
+
+error:
+ tp_channel_manager_emit_request_failed (self, request_token,
+ error->domain, error->code, error->message);
+ g_error_free (error);
+ return TRUE;
+}
+
+static gboolean
+example_callable_media_manager_create_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ return example_callable_media_manager_request (
+ EXAMPLE_CALLABLE_MEDIA_MANAGER (manager),
+ request_token, request_properties, TRUE);
+}
+
+static gboolean
+example_callable_media_manager_ensure_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ return example_callable_media_manager_request (
+ EXAMPLE_CALLABLE_MEDIA_MANAGER (manager),
+ request_token, request_properties, FALSE);
+}
+
+static void
+channel_manager_iface_init (gpointer g_iface,
+ gpointer iface_data G_GNUC_UNUSED)
+{
+ TpChannelManagerIface *iface = g_iface;
+
+ iface->foreach_channel = example_callable_media_manager_foreach_channel;
+ iface->foreach_channel_class =
+ example_callable_media_manager_foreach_channel_class;
+ iface->create_channel = example_callable_media_manager_create_channel;
+ iface->ensure_channel = example_callable_media_manager_ensure_channel;
+ /* In this channel manager, Request has the same semantics as Create
+ * (this matches telepathy-gabble's behaviour) */
+ iface->request_channel = example_callable_media_manager_create_channel;
+}
diff --git a/examples/cm/callable/media-manager.h b/examples/cm/callable/media-manager.h
new file mode 100644
index 0000000..5be239e
--- /dev/null
+++ b/examples/cm/callable/media-manager.h
@@ -0,0 +1,71 @@
+/*
+ * media-manager.h - header for an example channel manager
+ *
+ * Copyright © 2007-2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright © 2007-2009 Nokia Corporation
+ *
+ * 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 __EXAMPLE_CALLABLE_MEDIA_MANAGER_H__
+#define __EXAMPLE_CALLABLE_MEDIA_MANAGER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ExampleCallableMediaManager ExampleCallableMediaManager;
+typedef struct _ExampleCallableMediaManagerPrivate
+ ExampleCallableMediaManagerPrivate;
+
+typedef struct _ExampleCallableMediaManagerClass
+ ExampleCallableMediaManagerClass;
+typedef struct _ExampleCallableMediaManagerClassPrivate
+ ExampleCallableMediaManagerClassPrivate;
+
+struct _ExampleCallableMediaManagerClass {
+ GObjectClass parent_class;
+
+ ExampleCallableMediaManagerClassPrivate *priv;
+};
+
+struct _ExampleCallableMediaManager {
+ GObject parent;
+
+ ExampleCallableMediaManagerPrivate *priv;
+};
+
+GType example_callable_media_manager_get_type (void);
+
+/* TYPE MACROS */
+#define EXAMPLE_TYPE_CALLABLE_MEDIA_MANAGER \
+ (example_callable_media_manager_get_type ())
+#define EXAMPLE_CALLABLE_MEDIA_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), EXAMPLE_TYPE_CALLABLE_MEDIA_MANAGER, \
+ ExampleCallableMediaManager))
+#define EXAMPLE_CALLABLE_MEDIA_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), EXAMPLE_TYPE_CALLABLE_MEDIA_MANAGER, \
+ ExampleCallableMediaManagerClass))
+#define EXAMPLE_IS_CALLABLE_MEDIA_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), EXAMPLE_TYPE_CALLABLE_MEDIA_MANAGER))
+#define EXAMPLE_IS_CALLABLE_MEDIA_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), EXAMPLE_TYPE_CALLABLE_MEDIA_MANAGER))
+#define EXAMPLE_CALLABLE_MEDIA_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), EXAMPLE_TYPE_CALLABLE_MEDIA_MANAGER, \
+ ExampleCallableMediaManagerClass))
+
+G_END_DECLS
+
+#endif
--
1.5.6.5
More information about the telepathy-commits
mailing list