summaryrefslogtreecommitdiff
path: root/examples/cm
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2012-02-20 16:35:23 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2012-02-20 16:35:23 +0000
commitc99370d3e1532073f526378155bb5183a4f50a3f (patch)
tree66e5655beff01e7883f5342f5073cbab3ee2fba6 /examples/cm
parent89ebc5c794da4b2312ea299764f58de2bf037343 (diff)
parent50fb23a47944f2a47427010db697afe5e4a003df (diff)
downloadtelepathy-glib-c99370d3e1532073f526378155bb5183a4f50a3f.tar.gz
Merge remote-tracking branch 'origin/call1' into call1
Conflicts: docs/reference/telepathy-glib-docs.sgml docs/reference/telepathy-glib-sections.txt examples/future/call-cm/call-channel.c examples/future/call-cm/call-stream.c spec/Call_Content.xml spec/Call_Content_Interface_Audio_Control.xml spec/Call_Content_Interface_DTMF.xml spec/Call_Content_Interface_Media.xml spec/Call_Content_Interface_Video_Control.xml spec/Call_Content_Media_Description.xml spec/Call_Content_Media_Description_Interface_RTCP_Extended_Reports.xml spec/Call_Content_Media_Description_Interface_RTCP_Feedback.xml spec/Call_Content_Media_Description_Interface_RTP_Header_Extensions.xml spec/Call_Interface_Mute.xml spec/Call_Stream.xml spec/Call_Stream_Endpoint.xml spec/Call_Stream_Interface_Media.xml spec/Channel_Interface_DTMF.xml spec/Channel_Type_Call.xml spec/all.xml telepathy-glib/channel.xml telepathy-glib/extra-gtkdoc.h tests/dbus/call-example.c
Diffstat (limited to 'examples/cm')
-rw-r--r--examples/cm/Makefile.am2
-rw-r--r--examples/cm/call/Makefile.am (renamed from examples/cm/callable/Makefile.am)43
-rw-r--r--examples/cm/call/call-channel.c841
-rw-r--r--examples/cm/call/call-channel.h67
-rw-r--r--examples/cm/call/call-content.c103
-rw-r--r--examples/cm/call/call-content.h82
-rw-r--r--examples/cm/call/call-manager.c (renamed from examples/cm/callable/media-manager.c)211
-rw-r--r--examples/cm/call/call-manager.h71
-rw-r--r--examples/cm/call/call-stream.c481
-rw-r--r--examples/cm/call/call-stream.h80
-rw-r--r--examples/cm/call/cm.c (renamed from examples/cm/callable/connection-manager.c)35
-rw-r--r--examples/cm/call/cm.h73
-rw-r--r--examples/cm/call/conn.c (renamed from examples/cm/callable/conn.c)104
-rw-r--r--examples/cm/call/conn.h77
-rw-r--r--examples/cm/call/example_call.manager25
-rw-r--r--examples/cm/call/main.c (renamed from examples/cm/callable/main.c)12
-rw-r--r--examples/cm/call/protocol.c (renamed from examples/cm/callable/protocol.c)36
-rw-r--r--examples/cm/call/protocol.h64
-rw-r--r--examples/cm/callable/conn.h81
-rw-r--r--examples/cm/callable/connection-manager.h73
-rw-r--r--examples/cm/callable/example_callable.manager19
-rw-r--r--examples/cm/callable/media-channel.c1244
-rw-r--r--examples/cm/callable/media-channel.h73
-rw-r--r--examples/cm/callable/media-manager.h71
-rw-r--r--examples/cm/callable/media-stream.c652
-rw-r--r--examples/cm/callable/media-stream.h88
-rw-r--r--examples/cm/callable/protocol.h68
27 files changed, 2210 insertions, 2566 deletions
diff --git a/examples/cm/Makefile.am b/examples/cm/Makefile.am
index 49e67a034..bb2b6f143 100644
--- a/examples/cm/Makefile.am
+++ b/examples/cm/Makefile.am
@@ -1,5 +1,5 @@
SUBDIRS = \
- callable \
+ call \
channelspecific \
contactlist \
echo-message-parts \
diff --git a/examples/cm/callable/Makefile.am b/examples/cm/call/Makefile.am
index 0a04041ec..3b7ad1fac 100644
--- a/examples/cm/callable/Makefile.am
+++ b/examples/cm/call/Makefile.am
@@ -1,7 +1,7 @@
# Example connection manager with audio/video calls.
-EXAMPLES = telepathy-example-cm-callable
-noinst_LTLIBRARIES = libexample-cm-callable.la
+EXAMPLES = telepathy-example-cm-call
+noinst_LTLIBRARIES = libexample-cm-call.la
if INSTALL_EXAMPLES
libexec_PROGRAMS = $(EXAMPLES)
@@ -9,40 +9,42 @@ else
noinst_PROGRAMS = $(EXAMPLES)
endif
-libexample_cm_callable_la_SOURCES = \
+libexample_cm_call_la_SOURCES = \
+ cm.c \
+ cm.h \
conn.c \
conn.h \
- connection-manager.c \
- connection-manager.h \
- media-channel.c \
- media-channel.h \
- media-manager.c \
- media-manager.h \
- media-stream.c \
- media-stream.h \
+ call-channel.c \
+ call-channel.h \
+ call-manager.c \
+ call-manager.h \
+ call-content.c \
+ call-content.h \
+ call-stream.c \
+ call-stream.h \
protocol.c \
protocol.h
-libexample_cm_callable_la_LIBADD = $(LDADD)
+libexample_cm_call_la_LIBADD = $(LDADD)
-telepathy_example_cm_callable_SOURCES = \
+telepathy_example_cm_call_SOURCES = \
main.c
-telepathy_example_cm_callable_LDADD = \
+telepathy_example_cm_call_LDADD = \
$(noinst_LTLIBRARIES)
servicedir = ${datadir}/dbus-1/services
if INSTALL_EXAMPLES
-service_DATA = _gen/org.freedesktop.Telepathy.ConnectionManager.example_callable.service
+service_DATA = _gen/org.freedesktop.Telepathy.ConnectionManager.example_call.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"; } > $@
+ echo "Name=org.freedesktop.Telepathy.ConnectionManager.example_call" && \
+ echo "Exec=${libexecdir}/telepathy-example-cm-call"; } > $@
managerdir = ${datadir}/telepathy/managers
-dist_manager_DATA = example_callable.manager
+dist_manager_DATA = example_call.manager
endif
clean-local:
@@ -64,8 +66,9 @@ AM_CPPFLAGS = \
$(GLIB_CFLAGS) \
$(DBUS_CFLAGS) \
$(NULL)
-
-AM_CFLAGS = $(ERROR_CFLAGS)
AM_LDFLAGS = \
$(ERROR_LDFLAGS) \
$(NULL)
+
+AM_CFLAGS = $(ERROR_CFLAGS)
+
diff --git a/examples/cm/call/call-channel.c b/examples/cm/call/call-channel.c
new file mode 100644
index 000000000..677c4951a
--- /dev/null
+++ b/examples/cm/call/call-channel.c
@@ -0,0 +1,841 @@
+/*
+ * call-channel.c - an example 1-1 audio/video 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 has the HardwareStreaming flag, its contents
+ * and streams do not have the Media 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 do not have HardwareStreaming,
+ * and do have the Media interface on their contents/streams. 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 "call-channel.h"
+
+#include <string.h>
+
+#include <gobject/gvaluecollector.h>
+
+#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/channel-iface.h>
+#include <telepathy-glib/svc-channel.h>
+#include <telepathy-glib/svc-call.h>
+#include <telepathy-glib/telepathy-glib.h>
+
+#include "call-content.h"
+#include "call-stream.h"
+
+static void hold_iface_init (gpointer iface, gpointer data);
+
+G_DEFINE_TYPE_WITH_CODE (ExampleCallChannel,
+ example_call_channel,
+ TP_TYPE_BASE_MEDIA_CALL_CHANNEL,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_HOLD,
+ hold_iface_init))
+
+enum
+{
+ PROP_SIMULATION_DELAY = 1,
+ N_PROPS
+};
+
+struct _ExampleCallChannelPrivate
+{
+ guint simulation_delay;
+ TpBaseConnection *conn;
+ TpHandle handle;
+ gboolean locally_requested;
+
+ guint hold_state;
+ guint hold_state_reason;
+
+ guint next_stream_id;
+ gboolean closed;
+};
+
+static const char * example_call_channel_interfaces[] = {
+ TP_IFACE_CHANNEL_INTERFACE_HOLD,
+ NULL
+};
+
+/* In practice you need one for audio, plus one per video (e.g. a
+ * presentation might have separate video contents for the slides
+ * and a camera pointed at the presenter), so having more than three
+ * would be highly unusual */
+#define MAX_CONTENTS_PER_CALL 100
+
+G_GNUC_NULL_TERMINATED static void
+example_call_channel_set_state (ExampleCallChannel *self,
+ TpCallState state,
+ TpCallFlags flags,
+ TpHandle actor,
+ TpCallStateChangeReason reason,
+ const gchar *error,
+ ...)
+{
+ /* FIXME: TpBaseCallChannel is not that flexible */
+ tp_base_call_channel_set_state ((TpBaseCallChannel *) self,
+ state, actor, reason, error, "");
+}
+
+static void
+example_call_channel_init (ExampleCallChannel *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ EXAMPLE_TYPE_CALL_CHANNEL,
+ ExampleCallChannelPrivate);
+
+ self->priv->next_stream_id = 1;
+
+ self->priv->hold_state = TP_LOCAL_HOLD_STATE_UNHELD;
+ self->priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE;
+}
+
+static ExampleCallContent *example_call_channel_add_content (
+ ExampleCallChannel *self, TpMediaStreamType media_type,
+ gboolean locally_requested, gboolean initial,
+ const gchar *requested_name, GError **error);
+
+static void example_call_channel_initiate_outgoing (ExampleCallChannel *self);
+
+static void
+constructed (GObject *object)
+{
+ void (*chain_up) (GObject *) =
+ ((GObjectClass *) example_call_channel_parent_class)->constructed;
+ ExampleCallChannel *self = EXAMPLE_CALL_CHANNEL (object);
+ TpBaseChannel *base = (TpBaseChannel *) self;
+ TpBaseCallChannel *call = (TpBaseCallChannel *) self;
+
+ if (chain_up != NULL)
+ chain_up (object);
+
+ self->priv->handle = tp_base_channel_get_target_handle (base);
+ self->priv->locally_requested = tp_base_channel_is_requested (base);
+ self->priv->conn = tp_base_channel_get_connection (base);
+
+ tp_base_call_channel_update_member_flags (call, self->priv->handle, 0,
+ 0, TP_CALL_STATE_CHANGE_REASON_UNKNOWN, "", "");
+
+ if (self->priv->locally_requested)
+ {
+ /* Nobody is locally pending. The remote peer will turn up in
+ * remote-pending state when we actually contact them, which is done
+ * in example_call_channel_initiate_outgoing. */
+ example_call_channel_set_state (self,
+ TP_CALL_STATE_PENDING_INITIATOR, 0, 0,
+ TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED, "",
+ NULL);
+ }
+ else
+ {
+ /* This is an incoming call, so the self-handle is locally
+ * pending, to indicate that we need to answer. */
+ example_call_channel_set_state (self,
+ TP_CALL_STATE_INITIALISED, 0, self->priv->handle,
+ TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED, "",
+ NULL);
+ }
+
+ /* FIXME: should respect initial names */
+ if (tp_base_call_channel_has_initial_audio (call, NULL))
+ {
+ g_message ("Channel initially has an audio stream");
+ example_call_channel_add_content (self, TP_MEDIA_STREAM_TYPE_AUDIO,
+ self->priv->locally_requested, TRUE, NULL, NULL);
+ }
+
+ if (tp_base_call_channel_has_initial_video (call, NULL))
+ {
+ g_message ("Channel initially has a video stream");
+ example_call_channel_add_content (self, TP_MEDIA_STREAM_TYPE_VIDEO,
+ self->priv->locally_requested, TRUE, NULL, NULL);
+ }
+
+ tp_base_channel_register (base);
+}
+
+static void
+get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ExampleCallChannel *self = EXAMPLE_CALL_CHANNEL (object);
+
+ switch (property_id)
+ {
+ case PROP_SIMULATION_DELAY:
+ g_value_set_uint (value, self->priv->simulation_delay);
+ 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)
+{
+ ExampleCallChannel *self = EXAMPLE_CALL_CHANNEL (object);
+
+ switch (property_id)
+ {
+ case PROP_SIMULATION_DELAY:
+ self->priv->simulation_delay = g_value_get_uint (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+example_call_channel_terminate (ExampleCallChannel *self,
+ TpHandle actor,
+ TpChannelGroupChangeReason reason,
+ TpCallStateChangeReason call_reason,
+ const gchar *error_name)
+{
+ TpBaseCallChannel *base = (TpBaseCallChannel *) self;
+ TpCallState call_state = tp_base_call_channel_get_state (base);
+
+ if (call_state != TP_CALL_STATE_ENDED)
+ {
+ GList *contents;
+
+ example_call_channel_set_state (self,
+ TP_CALL_STATE_ENDED, 0, actor,
+ call_reason, error_name,
+ NULL);
+
+ /* FIXME: fd.o #24936 #c20: it's unclear in the spec whether we should
+ * remove peers on call termination or not. For now this example does. */
+ tp_base_call_channel_remove_member (base, self->priv->handle,
+ actor, call_reason, error_name, NULL);
+
+ if (actor == tp_base_connection_get_self_handle (self->priv->conn))
+ {
+ const gchar *send_reason;
+
+ /* In a real protocol these would be some sort of real protocol
+ * construct, like an XMPP error stanza or a SIP error code */
+ switch (reason)
+ {
+ case TP_CHANNEL_GROUP_CHANGE_REASON_BUSY:
+ send_reason = "<user-is-busy/>";
+ break;
+
+ case TP_CHANNEL_GROUP_CHANGE_REASON_NO_ANSWER:
+ send_reason = "<no-answer/>";
+ break;
+
+ default:
+ send_reason = "<call-terminated/>";
+ }
+
+ g_message ("SIGNALLING: send: Terminating call: %s", send_reason);
+ }
+
+ /* terminate all streams: to avoid modifying the hash table (in the
+ * streams-removed handler) while iterating over it, we have to copy the
+ * keys and iterate over those */
+ contents = tp_base_call_channel_get_contents (base);
+ contents = g_list_copy (contents);
+ for (; contents != NULL; contents = g_list_delete_link (contents, contents))
+ {
+ example_call_content_remove_stream (contents->data);
+ tp_base_call_channel_remove_content (base, contents->data,
+ 0, call_reason, error_name, "");
+ }
+ }
+}
+
+static void
+dispose (GObject *object)
+{
+ ExampleCallChannel *self = EXAMPLE_CALL_CHANNEL (object);
+
+ /* the manager is meant to hold a ref to us until we've closed */
+ g_assert (self->priv->closed);
+
+ ((GObjectClass *) example_call_channel_parent_class)->dispose (object);
+}
+
+static void
+close_channel (TpBaseChannel *base)
+{
+ ExampleCallChannel *self = EXAMPLE_CALL_CHANNEL (base);
+
+ example_call_channel_terminate (self,
+ tp_base_connection_get_self_handle (self->priv->conn),
+ TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
+ TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED, "");
+
+ self->priv->closed = TRUE;
+
+ tp_base_channel_destroyed (base);
+}
+
+static void call_accept (TpBaseCallChannel *self);
+static TpBaseCallContent * call_add_content (TpBaseCallChannel *self,
+ const gchar *name,
+ TpMediaStreamType media,
+ TpMediaStreamDirection initial_direction,
+ GError **error);
+static void call_hangup (TpBaseCallChannel *self,
+ guint reason,
+ const gchar *detailed_reason,
+ const gchar *message);
+
+static void
+example_call_channel_class_init (ExampleCallChannelClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+ TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass);
+ TpBaseCallChannelClass *call_class = (TpBaseCallChannelClass *) klass;
+ GParamSpec *param_spec;
+
+ g_type_class_add_private (klass,
+ sizeof (ExampleCallChannelPrivate));
+
+ call_class->accept = call_accept;
+ call_class->add_content = call_add_content;
+ call_class->hangup = call_hangup;
+
+ base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT;
+ base_class->interfaces = example_call_channel_interfaces;
+ base_class->close = close_channel;
+
+ object_class->constructed = constructed;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->dispose = dispose;
+
+ param_spec = g_param_spec_uint ("simulation-delay", "Simulation delay",
+ "Delay between simulated network events",
+ 0, G_MAXUINT32, 1000,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_SIMULATION_DELAY,
+ param_spec);
+}
+
+static gboolean
+simulate_contact_ended_cb (gpointer p)
+{
+ ExampleCallChannel *self = p;
+ TpBaseCallChannel *base = (TpBaseCallChannel *) self;
+ TpCallState call_state = tp_base_call_channel_get_state (base);
+
+ /* if the call has been cancelled while we were waiting for the
+ * contact to do so, do nothing! */
+ if (call_state == TP_CALL_STATE_ENDED)
+ return FALSE;
+
+ g_message ("SIGNALLING: receive: call terminated: <call-terminated/>");
+
+ example_call_channel_terminate (self, self->priv->handle,
+ TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
+ TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED, "");
+
+ return FALSE;
+}
+
+static gboolean
+simulate_contact_answered_cb (gpointer p)
+{
+ ExampleCallChannel *self = p;
+ TpBaseCallChannel *base = (TpBaseCallChannel *) self;
+ TpCallState call_state = tp_base_call_channel_get_state (base);
+ GList *contents;
+ TpHandleRepoIface *contact_repo;
+ const gchar *peer;
+
+ /* if the call has been cancelled while we were waiting for the
+ * contact to answer, do nothing! */
+ if (call_state == TP_CALL_STATE_ENDED)
+ return FALSE;
+
+ /* otherwise, we're waiting for a response from the contact, which now
+ * arrives */
+ g_assert_cmpuint (call_state, ==, TP_CALL_STATE_INITIALISED);
+
+ g_message ("SIGNALLING: receive: contact answered our call");
+
+ tp_base_call_channel_remote_accept (base);
+
+ contents = tp_base_call_channel_get_contents (base);
+ for (; contents != NULL; contents = contents->next)
+ {
+ ExampleCallStream *stream = example_call_content_get_stream (contents->data);
+
+ if (stream == NULL)
+ continue;
+
+ /* remote contact accepts our proposed stream direction */
+ example_call_stream_simulate_contact_agreed_to_send (stream);
+ }
+
+ contact_repo = tp_base_connection_get_handles
+ (self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+ peer = tp_handle_inspect (contact_repo, self->priv->handle);
+
+ /* If the contact's ID contains the magic string "(terminate)", simulate
+ * them hanging up after a moment. */
+ if (strstr (peer, "(terminate)") != NULL)
+ {
+ g_timeout_add_full (G_PRIORITY_DEFAULT,
+ self->priv->simulation_delay,
+ simulate_contact_ended_cb, g_object_ref (self),
+ g_object_unref);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+simulate_contact_busy_cb (gpointer p)
+{
+ ExampleCallChannel *self = p;
+ TpBaseCallChannel *base = (TpBaseCallChannel *) self;
+ TpCallState call_state = tp_base_call_channel_get_state (base);
+
+ /* if the call has been cancelled while we were waiting for the
+ * contact to answer, do nothing */
+ if (call_state == TP_CALL_STATE_ENDED)
+ return FALSE;
+
+ /* otherwise, we're waiting for a response from the contact, which now
+ * arrives */
+ g_assert_cmpuint (call_state, ==, TP_CALL_STATE_INITIALISED);
+
+ g_message ("SIGNALLING: receive: call terminated: <user-is-busy/>");
+
+ example_call_channel_terminate (self, self->priv->handle,
+ TP_CHANNEL_GROUP_CHANGE_REASON_BUSY,
+ TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED,
+ TP_ERROR_STR_BUSY);
+
+ return FALSE;
+}
+
+static ExampleCallContent *
+example_call_channel_add_content (ExampleCallChannel *self,
+ TpMediaStreamType media_type,
+ gboolean locally_requested,
+ gboolean initial,
+ const gchar *requested_name,
+ GError **error)
+{
+ TpBaseCallChannel *base = (TpBaseCallChannel *) self;
+ GList *contents;
+ const gchar *type_str;
+ TpHandle creator = self->priv->handle;
+ TpCallContentDisposition disposition =
+ TP_CALL_CONTENT_DISPOSITION_NONE;
+ guint id = self->priv->next_stream_id++;
+ ExampleCallContent *content;
+ ExampleCallStream *stream;
+ gchar *name;
+ gchar *path;
+ guint i;
+
+ /* an arbitrary limit much less than 2**32 means we don't use ridiculous
+ * amounts of memory, and also means @i can't wrap around when we use it to
+ * uniquify content names. */
+ contents = tp_base_call_channel_get_contents (base);
+ if (g_list_length (contents) > MAX_CONTENTS_PER_CALL)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_PERMISSION_DENIED,
+ "What are you doing with all those contents anyway?!");
+ return NULL;
+ }
+
+ type_str = (media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video");
+ if (tp_str_empty (requested_name))
+ {
+ requested_name = type_str;
+ }
+
+ for (i = 0; ; i++)
+ {
+ GList *l;
+
+ if (i == 0)
+ name = g_strdup (requested_name);
+ else
+ name = g_strdup_printf ("%s (%u)", requested_name, i);
+
+ for (l = contents; l != NULL; l = l->next)
+ {
+ if (!tp_strdiff (tp_base_call_content_get_name (l->data), name))
+ break;
+ }
+
+ if (l == NULL)
+ {
+ /* this name hasn't been used - good enough */
+ break;
+ }
+
+ g_free (name);
+ name = NULL;
+ }
+
+ if (initial)
+ disposition = TP_CALL_CONTENT_DISPOSITION_INITIAL;
+
+ if (locally_requested)
+ {
+ g_message ("SIGNALLING: send: new %s stream %s", type_str, name);
+ creator = self->priv->conn->self_handle;
+ }
+
+ path = g_strdup_printf ("%s/Content%u",
+ tp_base_channel_get_object_path ((TpBaseChannel *) self),
+ id);
+ content = g_object_new (EXAMPLE_TYPE_CALL_CONTENT,
+ "connection", self->priv->conn,
+ "creator", creator,
+ "media-type", media_type,
+ "name", name,
+ "disposition", disposition,
+ "object-path", path,
+ NULL);
+
+ tp_base_call_channel_add_content (base, (TpBaseCallContent *) content);
+ g_free (path);
+
+ path = g_strdup_printf ("%s/Stream%u",
+ tp_base_channel_get_object_path ((TpBaseChannel *) self),
+ id);
+ stream = g_object_new (EXAMPLE_TYPE_CALL_STREAM,
+ "connection", self->priv->conn,
+ "handle", self->priv->handle,
+ "locally-requested", locally_requested,
+ "object-path", path,
+ NULL);
+
+ example_call_content_add_stream (content, stream);
+ g_free (path);
+
+ g_object_unref (content);
+ g_object_unref (stream);
+
+ return content;
+}
+
+static gboolean
+simulate_contact_ringing_cb (gpointer p)
+{
+ ExampleCallChannel *self = p;
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
+ (self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+ const gchar *peer;
+
+ tp_base_call_channel_update_member_flags ((TpBaseCallChannel *) self,
+ self->priv->handle, TP_CALL_MEMBER_FLAG_RINGING,
+ 0, TP_CALL_STATE_CHANGE_REASON_UNKNOWN, "", "");
+
+ /* In this example there is no real contact, so just simulate them
+ * answering after a short time - unless the contact's name
+ * contains "(no answer)" or "(busy)" */
+
+ peer = tp_handle_inspect (contact_repo, self->priv->handle);
+
+ if (strstr (peer, "(busy)") != NULL)
+ {
+ g_timeout_add_full (G_PRIORITY_DEFAULT,
+ self->priv->simulation_delay,
+ simulate_contact_busy_cb, g_object_ref (self),
+ g_object_unref);
+ }
+ else if (strstr (peer, "(no answer)") != NULL)
+ {
+ /* do nothing - the call just rings forever */
+ }
+ else
+ {
+ g_timeout_add_full (G_PRIORITY_DEFAULT,
+ self->priv->simulation_delay,
+ simulate_contact_answered_cb, g_object_ref (self),
+ g_object_unref);
+ }
+
+ return FALSE;
+}
+
+static void
+example_call_channel_initiate_outgoing (ExampleCallChannel *self)
+{
+ g_message ("SIGNALLING: send: new streamed media call");
+
+ example_call_channel_set_state (self,
+ TP_CALL_STATE_INITIALISED, 0,
+ tp_base_connection_get_self_handle (self->priv->conn),
+ TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED, "",
+ NULL);
+
+ /* After a moment, we're sent an informational message saying it's ringing */
+ g_timeout_add_full (G_PRIORITY_DEFAULT,
+ self->priv->simulation_delay,
+ simulate_contact_ringing_cb, g_object_ref (self),
+ g_object_unref);
+}
+
+static void
+accept_incoming_call (ExampleCallChannel *self)
+{
+ TpBaseCallChannel *base = (TpBaseCallChannel *) self;
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
+ (self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+ GList *contents;
+
+ g_message ("SIGNALLING: send: Accepting incoming call from %s",
+ tp_handle_inspect (contact_repo, self->priv->handle));
+
+ example_call_channel_set_state (self,
+ TP_CALL_STATE_ACCEPTED, 0,
+ tp_base_connection_get_self_handle (self->priv->conn),
+ TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED, "",
+ NULL);
+
+ contents = tp_base_call_channel_get_contents (base);
+ for (; contents != NULL; contents = contents->next)
+ {
+ ExampleCallStream *stream = example_call_content_get_stream (contents->data);
+ guint disposition = tp_base_call_content_get_disposition (contents->data);
+
+ if (stream == NULL || disposition != TP_CALL_CONTENT_DISPOSITION_INITIAL)
+ continue;
+
+ /* we accept the proposed stream direction */
+ example_call_stream_accept_proposed_direction (stream);
+ }
+}
+
+static void
+call_accept (TpBaseCallChannel *base)
+{
+ ExampleCallChannel *self = EXAMPLE_CALL_CHANNEL (base);
+
+ if (self->priv->locally_requested)
+ {
+ /* Take the contents we've already added, and make them happen */
+ example_call_channel_initiate_outgoing (self);
+ }
+ else
+ {
+ accept_incoming_call (self);
+ }
+}
+
+static void
+call_hangup (TpBaseCallChannel *base,
+ guint reason,
+ const gchar *detailed_reason,
+ const gchar *message G_GNUC_UNUSED)
+{
+ ExampleCallChannel *self = EXAMPLE_CALL_CHANNEL (base);
+
+ example_call_channel_terminate (self,
+ tp_base_connection_get_self_handle (self->priv->conn),
+ TP_CHANNEL_GROUP_CHANGE_REASON_NONE, reason, detailed_reason);
+}
+
+static TpBaseCallContent *
+call_add_content (TpBaseCallChannel *base,
+ const gchar *content_name,
+ guint content_type,
+ TpMediaStreamDirection initial_direction,
+ GError **error)
+{
+ ExampleCallChannel *self = EXAMPLE_CALL_CHANNEL (base);
+
+ return (TpBaseCallContent *) example_call_channel_add_content (self,
+ content_type, TRUE, FALSE, content_name, error);
+}
+
+static gboolean
+simulate_hold (gpointer p)
+{
+ ExampleCallChannel *self = p;
+ TpBaseCallChannel *base = (TpBaseCallChannel *) self;
+ TpCallState call_state = tp_base_call_channel_get_state (base);
+ TpCallFlags call_flags = 0; /* FIXME */
+
+ self->priv->hold_state = TP_LOCAL_HOLD_STATE_HELD;
+ g_message ("SIGNALLING: hold state changed to held");
+ tp_svc_channel_interface_hold_emit_hold_state_changed (self,
+ self->priv->hold_state, self->priv->hold_state_reason);
+
+ example_call_channel_set_state (self, call_state,
+ call_flags | TP_CALL_FLAG_LOCALLY_HELD,
+ tp_base_connection_get_self_handle (self->priv->conn),
+ TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED, "", NULL);
+
+ return FALSE;
+}
+
+static gboolean
+simulate_unhold (gpointer p)
+{
+ ExampleCallChannel *self = p;
+ TpBaseCallChannel *base = (TpBaseCallChannel *) self;
+ TpCallState call_state = tp_base_call_channel_get_state (base);
+ TpCallFlags call_flags = 0; /* FIXME */
+
+ self->priv->hold_state = TP_LOCAL_HOLD_STATE_UNHELD;
+ g_message ("SIGNALLING: hold state changed to unheld");
+ tp_svc_channel_interface_hold_emit_hold_state_changed (self,
+ self->priv->hold_state, self->priv->hold_state_reason);
+
+ example_call_channel_set_state (self, call_state,
+ call_flags & ~TP_CALL_FLAG_LOCALLY_HELD,
+ tp_base_connection_get_self_handle (self->priv->conn),
+ TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED, "", NULL);
+
+ return FALSE;
+}
+
+static gboolean
+simulate_inability_to_unhold (gpointer p)
+{
+ ExampleCallChannel *self = p;
+
+ self->priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD;
+ g_message ("SIGNALLING: unable to unhold - hold state changed to "
+ "pending hold");
+ tp_svc_channel_interface_hold_emit_hold_state_changed (self,
+ self->priv->hold_state, self->priv->hold_state_reason);
+ /* hold again */
+ g_timeout_add_full (G_PRIORITY_DEFAULT,
+ self->priv->simulation_delay,
+ simulate_hold, g_object_ref (self),
+ g_object_unref);
+ return FALSE;
+}
+
+static void
+hold_get_hold_state (TpSvcChannelInterfaceHold *iface,
+ DBusGMethodInvocation *context)
+{
+ ExampleCallChannel *self = EXAMPLE_CALL_CHANNEL (iface);
+
+ tp_svc_channel_interface_hold_return_from_get_hold_state (context,
+ self->priv->hold_state, self->priv->hold_state_reason);
+}
+
+static void
+hold_request_hold (TpSvcChannelInterfaceHold *iface,
+ gboolean hold,
+ DBusGMethodInvocation *context)
+{
+ ExampleCallChannel *self = EXAMPLE_CALL_CHANNEL (iface);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
+ (self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+ GError *error = NULL;
+ const gchar *peer;
+ GSourceFunc callback;
+
+ if ((hold && self->priv->hold_state == TP_LOCAL_HOLD_STATE_HELD) ||
+ (!hold && self->priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD))
+ {
+ tp_svc_channel_interface_hold_return_from_request_hold (context);
+ return;
+ }
+
+ peer = tp_handle_inspect (contact_repo, self->priv->handle);
+
+ if (!hold && strstr (peer, "(no unhold)") != NULL)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "unable to unhold");
+ goto error;
+ }
+
+ self->priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_REQUESTED;
+
+ if (hold)
+ {
+ self->priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD;
+ callback = simulate_hold;
+ }
+ else
+ {
+ self->priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_UNHOLD;
+
+ peer = tp_handle_inspect (contact_repo, self->priv->handle);
+
+ if (strstr (peer, "(inability to unhold)") != NULL)
+ {
+ callback = simulate_inability_to_unhold;
+ }
+ else
+ {
+ callback = simulate_unhold;
+ }
+ }
+
+ g_message ("SIGNALLING: hold state changed to pending %s",
+ (hold ? "hold" : "unhold"));
+ tp_svc_channel_interface_hold_emit_hold_state_changed (iface,
+ self->priv->hold_state, self->priv->hold_state_reason);
+ /* No need to change the call flags - we never change the actual hold state
+ * here, only the pending hold state */
+
+ g_timeout_add_full (G_PRIORITY_DEFAULT,
+ self->priv->simulation_delay,
+ callback, g_object_ref (self),
+ g_object_unref);
+
+ tp_svc_channel_interface_hold_return_from_request_hold (context);
+ return;
+
+error:
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+}
+
+
+void
+hold_iface_init (gpointer iface,
+ gpointer data)
+{
+ TpSvcChannelInterfaceHoldClass *klass = iface;
+
+#define IMPLEMENT(x) \
+ tp_svc_channel_interface_hold_implement_##x (klass, hold_##x)
+ IMPLEMENT (get_hold_state);
+ IMPLEMENT (request_hold);
+#undef IMPLEMENT
+}
diff --git a/examples/cm/call/call-channel.h b/examples/cm/call/call-channel.h
new file mode 100644
index 000000000..58c1db34c
--- /dev/null
+++ b/examples/cm/call/call-channel.h
@@ -0,0 +1,67 @@
+/*
+ * call-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_CALL_CHANNEL_H
+#define EXAMPLE_CALL_CHANNEL_H
+
+#include <glib-object.h>
+#include <telepathy-glib/telepathy-glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ExampleCallChannel ExampleCallChannel;
+typedef struct _ExampleCallChannelPrivate
+ ExampleCallChannelPrivate;
+
+typedef struct _ExampleCallChannelClass
+ ExampleCallChannelClass;
+
+GType example_call_channel_get_type (void);
+
+#define EXAMPLE_TYPE_CALL_CHANNEL \
+ (example_call_channel_get_type ())
+#define EXAMPLE_CALL_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXAMPLE_TYPE_CALL_CHANNEL, \
+ ExampleCallChannel))
+#define EXAMPLE_CALL_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), EXAMPLE_TYPE_CALL_CHANNEL, \
+ ExampleCallChannelClass))
+#define EXAMPLE_IS_CALL_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXAMPLE_TYPE_CALL_CHANNEL))
+#define EXAMPLE_IS_CALL_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), EXAMPLE_TYPE_CALL_CHANNEL))
+#define EXAMPLE_CALL_CHANNEL_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), EXAMPLE_TYPE_CALL_CHANNEL, \
+ ExampleCallChannelClass))
+
+struct _ExampleCallChannelClass {
+ TpBaseMediaCallChannelClass parent_class;
+};
+
+struct _ExampleCallChannel {
+ TpBaseMediaCallChannel parent;
+
+ ExampleCallChannelPrivate *priv;
+};
+
+G_END_DECLS
+
+#endif
diff --git a/examples/cm/call/call-content.c b/examples/cm/call/call-content.c
new file mode 100644
index 000000000..2f81835bb
--- /dev/null
+++ b/examples/cm/call/call-content.c
@@ -0,0 +1,103 @@
+/*
+ * call-content.c - a content in a call.
+ *
+ * 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 "call-content.h"
+
+#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/svc-call.h>
+
+G_DEFINE_TYPE (ExampleCallContent,
+ example_call_content,
+ TP_TYPE_BASE_MEDIA_CALL_CONTENT)
+
+struct _ExampleCallContentPrivate
+{
+ ExampleCallStream *stream;
+};
+
+static void
+example_call_content_init (ExampleCallContent *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ EXAMPLE_TYPE_CALL_CONTENT,
+ ExampleCallContentPrivate);
+}
+
+static void
+dispose (GObject *object)
+{
+ ExampleCallContent *self = EXAMPLE_CALL_CONTENT (object);
+
+ g_clear_object (&self->priv->stream);
+
+ ((GObjectClass *) example_call_content_parent_class)->dispose (object);
+}
+
+static void
+example_call_content_class_init (ExampleCallContentClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+
+ g_type_class_add_private (klass,
+ sizeof (ExampleCallContentPrivate));
+
+ object_class->dispose = dispose;
+}
+
+ExampleCallStream *
+example_call_content_get_stream (ExampleCallContent *self)
+{
+ g_return_val_if_fail (EXAMPLE_IS_CALL_CONTENT (self), NULL);
+
+ return self->priv->stream;
+}
+
+void
+example_call_content_add_stream (ExampleCallContent *self,
+ ExampleCallStream *stream)
+{
+ g_return_if_fail (EXAMPLE_IS_CALL_CONTENT (self));
+ g_return_if_fail (EXAMPLE_IS_CALL_STREAM (stream));
+ g_return_if_fail (self->priv->stream == NULL);
+
+ self->priv->stream = g_object_ref (stream);
+
+ tp_base_call_content_add_stream ((TpBaseCallContent *) self,
+ (TpBaseCallStream *) stream);
+}
+
+void
+example_call_content_remove_stream (ExampleCallContent *self)
+{
+ TpBaseCallStream *stream;
+
+ g_return_if_fail (EXAMPLE_IS_CALL_CONTENT (self));
+ g_return_if_fail (self->priv->stream != NULL);
+
+ stream = (TpBaseCallStream *) self->priv->stream;
+ self->priv->stream = NULL;
+
+ tp_base_call_content_remove_stream ((TpBaseCallContent *) self, stream,
+ 0, TP_CALL_STATE_CHANGE_REASON_UNKNOWN, "", "");
+
+ g_object_unref (stream);
+}
diff --git a/examples/cm/call/call-content.h b/examples/cm/call/call-content.h
new file mode 100644
index 000000000..06a5a5415
--- /dev/null
+++ b/examples/cm/call/call-content.h
@@ -0,0 +1,82 @@
+/*
+ * call-content.h - header for an example content
+ *
+ * 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_CALL_CONTENT_H
+#define EXAMPLE_CALL_CONTENT_H
+
+#include <glib-object.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+
+#include "call-stream.h"
+
+G_BEGIN_DECLS
+
+typedef struct _ExampleCallContent ExampleCallContent;
+typedef struct _ExampleCallContentPrivate
+ ExampleCallContentPrivate;
+
+typedef struct _ExampleCallContentClass
+ ExampleCallContentClass;
+typedef struct _ExampleCallContentClassPrivate
+ ExampleCallContentClassPrivate;
+
+GType example_call_content_get_type (void);
+
+#define EXAMPLE_TYPE_CALL_CONTENT \
+ (example_call_content_get_type ())
+#define EXAMPLE_CALL_CONTENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXAMPLE_TYPE_CALL_CONTENT, \
+ ExampleCallContent))
+#define EXAMPLE_CALL_CONTENT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), EXAMPLE_TYPE_CALL_CONTENT, \
+ ExampleCallContentClass))
+#define EXAMPLE_IS_CALL_CONTENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXAMPLE_TYPE_CALL_CONTENT))
+#define EXAMPLE_IS_CALL_CONTENT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), EXAMPLE_TYPE_CALL_CONTENT))
+#define EXAMPLE_CALL_CONTENT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), EXAMPLE_TYPE_CALL_CONTENT, \
+ ExampleCallContentClass))
+
+struct _ExampleCallContentClass {
+ TpBaseMediaCallContentClass parent_class;
+
+ ExampleCallContentClassPrivate *priv;
+};
+
+struct _ExampleCallContent {
+ TpBaseMediaCallContent parent;
+
+ ExampleCallContentPrivate *priv;
+};
+
+/* In this example, each content can only have one stream. */
+ExampleCallStream *example_call_content_get_stream (ExampleCallContent *self);
+
+void example_call_content_add_stream (ExampleCallContent *self,
+ ExampleCallStream *stream);
+
+void example_call_content_remove_stream (ExampleCallContent *self);
+
+G_END_DECLS
+
+#endif
diff --git a/examples/cm/callable/media-manager.c b/examples/cm/call/call-manager.c
index b24a65774..8f1ac61be 100644
--- a/examples/cm/callable/media-manager.c
+++ b/examples/cm/call/call-manager.c
@@ -1,5 +1,6 @@
/*
- * media-manager.c - an example channel manager for StreamedMedia calls.
+ * call-manager.c - an example channel manager for Call channels.
+ *
* This channel manager emulates a protocol like XMPP Jingle, where you can
* make several simultaneous calls to the same or different contacts.
*
@@ -23,7 +24,7 @@
#include "config.h"
-#include "media-manager.h"
+#include "call-manager.h"
#include <dbus/dbus-glib.h>
@@ -33,12 +34,12 @@
#include <telepathy-glib/errors.h>
#include <telepathy-glib/interfaces.h>
-#include "media-channel.h"
+#include "call-channel.h"
static void channel_manager_iface_init (gpointer, gpointer);
-G_DEFINE_TYPE_WITH_CODE (ExampleCallableMediaManager,
- example_callable_media_manager,
+G_DEFINE_TYPE_WITH_CODE (ExampleCallManager,
+ example_call_manager,
G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER,
channel_manager_iface_init))
@@ -52,17 +53,17 @@ enum
N_PROPS
};
-struct _ExampleCallableMediaManagerPrivate
+struct _ExampleCallManagerPrivate
{
TpBaseConnection *conn;
guint simulation_delay;
- /* Map from reffed ExampleCallableMediaChannel to the same pointer; used as a
+ /* Map from reffed ExampleCallChannel to the same pointer; used as a
* set.
*/
GHashTable *channels;
- /* Next channel will be ("MediaChannel%u", next_channel_index) */
+ /* Next channel will be ("CallChannel%u", next_channel_index) */
guint next_channel_index;
gulong status_changed_id;
@@ -70,11 +71,11 @@ struct _ExampleCallableMediaManagerPrivate
};
static void
-example_callable_media_manager_init (ExampleCallableMediaManager *self)
+example_call_manager_init (ExampleCallManager *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- EXAMPLE_TYPE_CALLABLE_MEDIA_MANAGER,
- ExampleCallableMediaManagerPrivate);
+ EXAMPLE_TYPE_CALL_MANAGER,
+ ExampleCallManagerPrivate);
self->priv->conn = NULL;
self->priv->channels = g_hash_table_new_full (NULL, NULL, g_object_unref,
@@ -84,14 +85,21 @@ example_callable_media_manager_init (ExampleCallableMediaManager *self)
}
static void
-example_callable_media_manager_close_all (ExampleCallableMediaManager *self)
+example_call_manager_close_all (ExampleCallManager *self)
{
if (self->priv->channels != NULL)
{
GHashTable *tmp = self->priv->channels;
+ GHashTableIter iter;
+ gpointer v;
self->priv->channels = NULL;
+ g_hash_table_iter_init (&iter, tmp);
+
+ while (g_hash_table_iter_next (&iter, NULL, &v))
+ tp_base_channel_close (v);
+
g_hash_table_unref (tmp);
}
@@ -113,22 +121,22 @@ example_callable_media_manager_close_all (ExampleCallableMediaManager *self)
static void
dispose (GObject *object)
{
- ExampleCallableMediaManager *self = EXAMPLE_CALLABLE_MEDIA_MANAGER (object);
+ ExampleCallManager *self = EXAMPLE_CALL_MANAGER (object);
- example_callable_media_manager_close_all (self);
+ example_call_manager_close_all (self);
g_assert (self->priv->channels == NULL);
- ((GObjectClass *) example_callable_media_manager_parent_class)->dispose (
+ ((GObjectClass *) example_call_manager_parent_class)->dispose (
object);
}
static void
get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- ExampleCallableMediaManager *self = EXAMPLE_CALLABLE_MEDIA_MANAGER (object);
+ ExampleCallManager *self = EXAMPLE_CALL_MANAGER (object);
switch (property_id)
{
@@ -147,11 +155,11 @@ get_property (GObject *object,
static void
set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
- ExampleCallableMediaManager *self = EXAMPLE_CALLABLE_MEDIA_MANAGER (object);
+ ExampleCallManager *self = EXAMPLE_CALL_MANAGER (object);
switch (property_id)
{
@@ -175,13 +183,13 @@ static void
status_changed_cb (TpBaseConnection *conn,
guint status,
guint reason,
- ExampleCallableMediaManager *self)
+ ExampleCallManager *self)
{
switch (status)
{
case TP_CONNECTION_STATUS_DISCONNECTED:
{
- example_callable_media_manager_close_all (self);
+ example_call_manager_close_all (self);
}
break;
@@ -190,14 +198,14 @@ status_changed_cb (TpBaseConnection *conn,
}
}
-static ExampleCallableMediaChannel *new_channel (
- ExampleCallableMediaManager *self, TpHandle handle, TpHandle initiator,
- gpointer request_token, gboolean initial_audio, gboolean initial_video);
+static ExampleCallChannel *new_channel (ExampleCallManager *self,
+ TpHandle handle, TpHandle initiator, gpointer request_token,
+ gboolean initial_audio, gboolean initial_video);
static gboolean
simulate_incoming_call_cb (gpointer p)
{
- ExampleCallableMediaManager *self = p;
+ ExampleCallManager *self = p;
TpHandleRepoIface *contact_repo;
TpHandle caller;
@@ -221,8 +229,8 @@ simulate_incoming_call_cb (gpointer p)
* a contact */
static void
available_cb (GObject *conn G_GNUC_UNUSED,
- const gchar *message,
- ExampleCallableMediaManager *self)
+ const gchar *message,
+ ExampleCallManager *self)
{
g_timeout_add_full (G_PRIORITY_DEFAULT, self->priv->simulation_delay,
simulate_incoming_call_cb, g_object_ref (self), g_object_unref);
@@ -231,9 +239,9 @@ available_cb (GObject *conn G_GNUC_UNUSED,
static void
constructed (GObject *object)
{
- ExampleCallableMediaManager *self = EXAMPLE_CALLABLE_MEDIA_MANAGER (object);
+ ExampleCallManager *self = EXAMPLE_CALL_MANAGER (object);
void (*chain_up) (GObject *) =
- ((GObjectClass *) example_callable_media_manager_parent_class)->constructed;
+ ((GObjectClass *) example_call_manager_parent_class)->constructed;
if (chain_up != NULL)
{
@@ -248,8 +256,7 @@ constructed (GObject *object)
}
static void
-example_callable_media_manager_class_init (
- ExampleCallableMediaManagerClass *klass)
+example_call_manager_class_init (ExampleCallManagerClass *klass)
{
GParamSpec *param_spec;
GObjectClass *object_class = (GObjectClass *) klass;
@@ -273,16 +280,15 @@ example_callable_media_manager_class_init (
param_spec);
g_type_class_add_private (klass,
- sizeof (ExampleCallableMediaManagerPrivate));
+ sizeof (ExampleCallManagerPrivate));
}
static void
-example_callable_media_manager_foreach_channel (
- TpChannelManager *iface,
+example_call_manager_foreach_channel (TpChannelManager *iface,
TpExportableChannelFunc callback,
gpointer user_data)
{
- ExampleCallableMediaManager *self = EXAMPLE_CALLABLE_MEDIA_MANAGER (iface);
+ ExampleCallManager *self = EXAMPLE_CALL_MANAGER (iface);
GHashTableIter iter;
gpointer chan;
@@ -293,8 +299,8 @@ example_callable_media_manager_foreach_channel (
}
static void
-channel_closed_cb (ExampleCallableMediaChannel *chan,
- ExampleCallableMediaManager *self)
+channel_closed_cb (ExampleCallChannel *chan,
+ ExampleCallManager *self)
{
tp_channel_manager_emit_channel_closed_for_object (self,
TP_EXPORTABLE_CHANNEL (chan));
@@ -303,24 +309,24 @@ channel_closed_cb (ExampleCallableMediaChannel *chan,
g_hash_table_remove (self->priv->channels, chan);
}
-static ExampleCallableMediaChannel *
-new_channel (ExampleCallableMediaManager *self,
- TpHandle handle,
- TpHandle initiator,
- gpointer request_token,
- gboolean initial_audio,
- gboolean initial_video)
+static ExampleCallChannel *
+new_channel (ExampleCallManager *self,
+ TpHandle handle,
+ TpHandle initiator,
+ gpointer request_token,
+ gboolean initial_audio,
+ gboolean initial_video)
{
- ExampleCallableMediaChannel *chan;
+ ExampleCallChannel *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",
+ object_path = g_strdup_printf ("%s/CallChannel%u",
self->priv->conn->object_path, self->priv->next_channel_index++);
- chan = g_object_new (EXAMPLE_TYPE_CALLABLE_MEDIA_CHANNEL,
+ chan = g_object_new (EXAMPLE_TYPE_CALL_CHANNEL,
"connection", self->priv->conn,
"object-path", object_path,
"handle", handle,
@@ -329,6 +335,7 @@ new_channel (ExampleCallableMediaManager *self,
"simulation-delay", self->priv->simulation_delay,
"initial-audio", initial_audio,
"initial-video", initial_video,
+ "mutable-contents", TRUE,
NULL);
g_free (object_path);
@@ -347,46 +354,70 @@ new_channel (ExampleCallableMediaManager *self,
return chan;
}
-static const gchar * const fixed_properties[] = {
+static const gchar * const audio_fixed_properties[] = {
TP_PROP_CHANNEL_CHANNEL_TYPE,
TP_PROP_CHANNEL_TARGET_HANDLE_TYPE,
+ TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO,
+ NULL
+};
+
+static const gchar * const video_fixed_properties[] = {
+ TP_PROP_CHANNEL_CHANNEL_TYPE,
+ TP_PROP_CHANNEL_TARGET_HANDLE_TYPE,
+ TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO,
+ NULL
+};
+
+static const gchar * const audio_allowed_properties[] = {
+ TP_PROP_CHANNEL_TARGET_HANDLE,
+ TP_PROP_CHANNEL_TARGET_ID,
+ TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO,
NULL
};
-static const gchar * const allowed_properties[] = {
+static const gchar * const video_allowed_properties[] = {
TP_PROP_CHANNEL_TARGET_HANDLE,
TP_PROP_CHANNEL_TARGET_ID,
+ TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO,
NULL
};
static void
-example_callable_media_manager_type_foreach_channel_class (GType type,
+example_call_manager_type_foreach_channel_class (GType type,
TpChannelManagerTypeChannelClassFunc func,
gpointer user_data)
{
GHashTable *table = tp_asv_new (
TP_PROP_CHANNEL_CHANNEL_TYPE,
- G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
+ G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_CALL,
TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
+ TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, G_TYPE_BOOLEAN, TRUE,
NULL);
- func (type, table, allowed_properties, user_data);
+ func (type, table, audio_allowed_properties, user_data);
+
+ g_hash_table_remove (table, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO);
+ tp_asv_set_boolean (table, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO,
+ TRUE);
+
+ func (type, table, video_allowed_properties, user_data);
g_hash_table_unref (table);
}
static gboolean
-example_callable_media_manager_request (ExampleCallableMediaManager *self,
- gpointer request_token,
- GHashTable *request_properties,
- gboolean require_new)
+example_call_manager_request (ExampleCallManager *self,
+ gpointer request_token,
+ GHashTable *request_properties,
+ gboolean require_new)
{
TpHandle handle;
GError *error = NULL;
+ gboolean initial_audio, initial_video;
if (tp_strdiff (tp_asv_get_string (request_properties,
TP_PROP_CHANNEL_CHANNEL_TYPE),
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA))
+ TP_IFACE_CHANNEL_TYPE_CALL))
{
return FALSE;
}
@@ -401,8 +432,22 @@ example_callable_media_manager_request (ExampleCallableMediaManager *self,
TP_PROP_CHANNEL_TARGET_HANDLE, NULL);
g_assert (handle != 0);
+ initial_audio = tp_asv_get_boolean (request_properties,
+ TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, NULL);
+ initial_video = tp_asv_get_boolean (request_properties,
+ TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, NULL);
+
+ if (!initial_audio && !initial_video)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ "Call channels must initially have either audio or video content");
+ goto error;
+ }
+
+ /* the set of (fixed | allowed) properties is the same for audio and video,
+ * so we only need to check with one set */
if (tp_channel_manager_asv_has_unknown_properties (request_properties,
- fixed_properties, allowed_properties, &error))
+ audio_fixed_properties, audio_allowed_properties, &error))
{
goto error;
}
@@ -445,8 +490,8 @@ example_callable_media_manager_request (ExampleCallableMediaManager *self,
}
}
- new_channel (self, handle, self->priv->conn->self_handle,
- request_token, FALSE, FALSE);
+ new_channel (self, handle, self->priv->conn->self_handle, request_token,
+ initial_audio, initial_video);
return TRUE;
error:
@@ -457,41 +502,37 @@ error:
}
static gboolean
-example_callable_media_manager_create_channel (TpChannelManager *manager,
- gpointer request_token,
- GHashTable *request_properties)
+example_call_manager_create_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
{
- return example_callable_media_manager_request (
- EXAMPLE_CALLABLE_MEDIA_MANAGER (manager),
+ return example_call_manager_request (
+ EXAMPLE_CALL_MANAGER (manager),
request_token, request_properties, TRUE);
}
static gboolean
-example_callable_media_manager_ensure_channel (TpChannelManager *manager,
- gpointer request_token,
- GHashTable *request_properties)
+example_call_manager_ensure_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
{
- return example_callable_media_manager_request (
- EXAMPLE_CALLABLE_MEDIA_MANAGER (manager),
+ return example_call_manager_request (
+ EXAMPLE_CALL_MANAGER (manager),
request_token, request_properties, FALSE);
}
static void
channel_manager_iface_init (gpointer g_iface,
- gpointer iface_data G_GNUC_UNUSED)
+ gpointer iface_data G_GNUC_UNUSED)
{
TpChannelManagerIface *iface = g_iface;
- iface->foreach_channel = example_callable_media_manager_foreach_channel;
+ iface->foreach_channel = example_call_manager_foreach_channel;
iface->type_foreach_channel_class =
- example_callable_media_manager_type_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, RequestChannel is not supported (it's new
- * code so there's no reason to be backwards compatible). The requirements
- * for RequestChannel are somewhat complicated for backwards compatibility
- * reasons: see telepathy-gabble or
- * http://telepathy.freedesktop.org/wiki/Requesting%20StreamedMedia%20channels
- * for the gory details. */
+ example_call_manager_type_foreach_channel_class;
+ iface->create_channel = example_call_manager_create_channel;
+ iface->ensure_channel = example_call_manager_ensure_channel;
+ /* In this channel manager, RequestChannel is not supported; Call is not
+ * designed to work with the old RequestChannel API. */
iface->request_channel = NULL;
}
diff --git a/examples/cm/call/call-manager.h b/examples/cm/call/call-manager.h
new file mode 100644
index 000000000..96f5aee39
--- /dev/null
+++ b/examples/cm/call/call-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_CALL_MANAGER_H
+#define EXAMPLE_CALL_MANAGER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ExampleCallManager ExampleCallManager;
+typedef struct _ExampleCallManagerPrivate
+ ExampleCallManagerPrivate;
+
+typedef struct _ExampleCallManagerClass
+ ExampleCallManagerClass;
+typedef struct _ExampleCallManagerClassPrivate
+ ExampleCallManagerClassPrivate;
+
+struct _ExampleCallManagerClass {
+ GObjectClass parent_class;
+
+ ExampleCallManagerClassPrivate *priv;
+};
+
+struct _ExampleCallManager {
+ GObject parent;
+
+ ExampleCallManagerPrivate *priv;
+};
+
+GType example_call_manager_get_type (void);
+
+/* TYPE MACROS */
+#define EXAMPLE_TYPE_CALL_MANAGER \
+ (example_call_manager_get_type ())
+#define EXAMPLE_CALL_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), EXAMPLE_TYPE_CALL_MANAGER, \
+ ExampleCallManager))
+#define EXAMPLE_CALL_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), EXAMPLE_TYPE_CALL_MANAGER, \
+ ExampleCallManagerClass))
+#define EXAMPLE_IS_CALL_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), EXAMPLE_TYPE_CALL_MANAGER))
+#define EXAMPLE_IS_CALL_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), EXAMPLE_TYPE_CALL_MANAGER))
+#define EXAMPLE_CALL_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), EXAMPLE_TYPE_CALL_MANAGER, \
+ ExampleCallManagerClass))
+
+G_END_DECLS
+
+#endif
diff --git a/examples/cm/call/call-stream.c b/examples/cm/call/call-stream.c
new file mode 100644
index 000000000..c8fe4f28d
--- /dev/null
+++ b/examples/cm/call/call-stream.c
@@ -0,0 +1,481 @@
+/*
+ * call-stream.c - a stream in a call.
+ *
+ * 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 "call-stream.h"
+
+#include <telepathy-glib/base-connection.h>
+#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/svc-call.h>
+
+G_DEFINE_TYPE (ExampleCallStream,
+ example_call_stream,
+ TP_TYPE_BASE_MEDIA_CALL_STREAM)
+
+enum
+{
+ PROP_SIMULATION_DELAY = 1,
+ PROP_LOCALLY_REQUESTED,
+ PROP_HANDLE,
+ N_PROPS
+};
+
+struct _ExampleCallStreamPrivate
+{
+ guint simulation_delay;
+ gboolean locally_requested;
+ TpHandle handle;
+ guint agreed_delay_id;
+};
+
+static void
+example_call_stream_init (ExampleCallStream *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ EXAMPLE_TYPE_CALL_STREAM,
+ ExampleCallStreamPrivate);
+}
+
+static void example_call_stream_receive_direction_request (
+ ExampleCallStream *self, gboolean local_send, gboolean remote_send);
+static void example_call_stream_change_direction (ExampleCallStream *self,
+ gboolean want_to_send, gboolean want_to_receive);
+
+static void
+constructed (GObject *object)
+{
+ ExampleCallStream *self = EXAMPLE_CALL_STREAM (object);
+ void (*chain_up) (GObject *) =
+ ((GObjectClass *) example_call_stream_parent_class)->constructed;
+ static guint count = 0;
+ TpBaseConnection *conn;
+ TpDBusDaemon *dbus;
+ gchar *object_path;
+ TpCallStreamEndpoint *endpoint;
+
+ if (chain_up != NULL)
+ chain_up (object);
+
+ conn = tp_base_call_stream_get_connection ((TpBaseCallStream *) self);
+ dbus = tp_base_connection_get_dbus_daemon (conn);
+ object_path = g_strdup_printf ("%s/Endpoint%d",
+ tp_base_call_stream_get_object_path ((TpBaseCallStream *) self),
+ count++);
+ endpoint = tp_call_stream_endpoint_new (dbus, object_path,
+ TP_STREAM_TRANSPORT_TYPE_RAW_UDP, FALSE);
+
+ tp_base_media_call_stream_add_endpoint ((TpBaseMediaCallStream *) self,
+ endpoint);
+
+ if (self->priv->locally_requested)
+ {
+ example_call_stream_change_direction (self, TRUE, TRUE);
+ }
+ else
+ {
+ example_call_stream_receive_direction_request (self, TRUE, TRUE);
+ }
+
+ g_object_unref (endpoint);
+ g_free (object_path);
+}
+
+static void
+get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ExampleCallStream *self = EXAMPLE_CALL_STREAM (object);
+
+ switch (property_id)
+ {
+ case PROP_SIMULATION_DELAY:
+ g_value_set_uint (value, self->priv->simulation_delay);
+ break;
+
+ case PROP_LOCALLY_REQUESTED:
+ g_value_set_boolean (value, self->priv->locally_requested);
+ break;
+
+ case PROP_HANDLE:
+ g_value_set_uint (value, self->priv->handle);
+ 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)
+{
+ ExampleCallStream *self = EXAMPLE_CALL_STREAM (object);
+
+ switch (property_id)
+ {
+ case PROP_SIMULATION_DELAY:
+ self->priv->simulation_delay = g_value_get_uint (value);
+ break;
+
+ case PROP_LOCALLY_REQUESTED:
+ self->priv->locally_requested = g_value_get_boolean (value);
+ break;
+
+ case PROP_HANDLE:
+ self->priv->handle = g_value_get_uint (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static gboolean stream_request_receiving (TpBaseCallStream *base,
+ TpHandle contact,
+ gboolean receive,
+ GError **error);
+static gboolean stream_set_sending (TpBaseCallStream *base,
+ gboolean sending,
+ GError **error);
+
+static void
+finalize (GObject *object)
+{
+ ExampleCallStream *self = EXAMPLE_CALL_STREAM (object);
+
+ if (self->priv->agreed_delay_id != 0)
+ g_source_remove (self->priv->agreed_delay_id);
+
+ G_OBJECT_CLASS (example_call_stream_parent_class)->finalize (object);
+}
+
+static void
+example_call_stream_class_init (ExampleCallStreamClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+ TpBaseCallStreamClass *stream_class = (TpBaseCallStreamClass *) klass;
+ GParamSpec *param_spec;
+
+ g_type_class_add_private (klass, sizeof (ExampleCallStreamPrivate));
+
+ object_class->constructed = constructed;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->finalize = finalize;
+
+ stream_class->request_receiving = stream_request_receiving;
+ stream_class->set_sending = stream_set_sending;
+
+ param_spec = g_param_spec_uint ("simulation-delay", "Simulation delay",
+ "Delay between simulated network events",
+ 0, G_MAXUINT32, 1000,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_SIMULATION_DELAY,
+ param_spec);
+
+ param_spec = g_param_spec_boolean ("locally-requested", "Locally requested?",
+ "True if this channel was requested by the local user",
+ FALSE,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_LOCALLY_REQUESTED,
+ param_spec);
+
+ param_spec = g_param_spec_uint ("handle", "Peer's TpHandle",
+ "The handle with which this stream communicates or 0 if not applicable",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_HANDLE, param_spec);
+}
+
+void
+example_call_stream_accept_proposed_direction (ExampleCallStream *self)
+{
+ TpBaseCallStream *base = (TpBaseCallStream *) self;
+ TpSendingState state = tp_base_call_stream_get_local_sending_state (base);
+
+ if (state != TP_SENDING_STATE_PENDING_SEND)
+ return;
+
+ tp_base_call_stream_update_local_sending_state (base,
+ TP_SENDING_STATE_SENDING, 0, TP_CALL_STATE_CHANGE_REASON_UNKNOWN,
+ "", "");
+}
+
+void
+example_call_stream_simulate_contact_agreed_to_send (ExampleCallStream *self)
+{
+ TpBaseCallStream *base = (TpBaseCallStream *) self;
+ TpSendingState state = tp_base_call_stream_get_remote_sending_state (base,
+ self->priv->handle);
+
+ if (state != TP_SENDING_STATE_PENDING_SEND)
+
+ g_message ("%s: SIGNALLING: Sending to server: OK, I'll send you media",
+ tp_base_call_stream_get_object_path (base));
+
+ tp_base_call_stream_update_remote_sending_state ((TpBaseCallStream *) self,
+ self->priv->handle, TP_SENDING_STATE_SENDING, 0,
+ TP_CALL_STATE_CHANGE_REASON_UNKNOWN, "", "");
+}
+
+static gboolean
+simulate_contact_agreed_to_send_cb (gpointer p)
+{
+ example_call_stream_simulate_contact_agreed_to_send (p);
+ return FALSE;
+}
+
+static void
+example_call_stream_change_direction (ExampleCallStream *self,
+ gboolean want_to_send, gboolean want_to_receive)
+{
+ TpBaseCallStream *base = (TpBaseCallStream *) self;
+ TpSendingState local_sending_state =
+ tp_base_call_stream_get_local_sending_state (base);
+ TpSendingState remote_sending_state =
+ tp_base_call_stream_get_remote_sending_state (base, self->priv->handle);
+
+ if (want_to_send)
+ {
+ if (local_sending_state != TP_SENDING_STATE_SENDING)
+ {
+ if (local_sending_state == TP_SENDING_STATE_PENDING_SEND)
+ {
+ g_message ("%s: SIGNALLING: send: I will now send you media",
+ tp_base_call_stream_get_object_path (base));
+ }
+
+ g_message ("%s: MEDIA: sending media to peer",
+ tp_base_call_stream_get_object_path (base));
+
+ tp_base_call_stream_update_local_sending_state (base,
+ TP_SENDING_STATE_SENDING, 0, TP_CALL_STATE_CHANGE_REASON_UNKNOWN,
+ "", "");
+ }
+ }
+ else
+ {
+ if (local_sending_state == TP_SENDING_STATE_SENDING)
+ {
+ g_message ("%s: SIGNALLING: send: I will no longer send you media",
+ tp_base_call_stream_get_object_path (base));
+ g_message ("%s: MEDIA: no longer sending media to peer",
+ tp_base_call_stream_get_object_path (base));
+
+ tp_base_call_stream_update_local_sending_state (base,
+ TP_SENDING_STATE_NONE, 0, TP_CALL_STATE_CHANGE_REASON_UNKNOWN,
+ "", "");
+ }
+ else if (local_sending_state == TP_SENDING_STATE_PENDING_SEND)
+ {
+ g_message ("%s: SIGNALLING: send: refusing to send you media",
+ tp_base_call_stream_get_object_path (base));
+
+ tp_base_call_stream_update_local_sending_state (base,
+ TP_SENDING_STATE_NONE, 0, TP_CALL_STATE_CHANGE_REASON_UNKNOWN,
+ "", "");
+ }
+ }
+
+ if (want_to_receive)
+ {
+ if (remote_sending_state == TP_SENDING_STATE_NONE)
+ {
+ g_message ("%s: SIGNALLING: send: send me media, please?",
+ tp_base_call_stream_get_object_path (base));
+
+ tp_base_call_stream_update_remote_sending_state (
+ (TpBaseCallStream *) self,
+ self->priv->handle, TP_SENDING_STATE_PENDING_SEND, 0,
+ TP_CALL_STATE_CHANGE_REASON_UNKNOWN, "", "");
+
+ if (self->priv->agreed_delay_id == 0)
+ {
+ self->priv->agreed_delay_id = g_timeout_add (
+ self->priv->simulation_delay,
+ simulate_contact_agreed_to_send_cb, self);
+ }
+ }
+ }
+ else
+ {
+ if (remote_sending_state != TP_SENDING_STATE_NONE)
+ {
+ g_message ("%s: SIGNALLING: send: Please stop sending me media",
+ tp_base_call_stream_get_object_path (base));
+ g_message ("%s: MEDIA: suppressing output of stream",
+ tp_base_call_stream_get_object_path (base));
+
+ tp_base_call_stream_update_remote_sending_state (
+ (TpBaseCallStream *) self,
+ self->priv->handle, TP_SENDING_STATE_NONE, 0,
+ TP_CALL_STATE_CHANGE_REASON_UNKNOWN, "", "");
+ }
+ }
+}
+
+/* The remote user wants to change the direction of this stream according
+ * to @local_send and @remote_send. Shall we let him? */
+static void
+example_call_stream_receive_direction_request (ExampleCallStream *self,
+ gboolean local_send,
+ gboolean remote_send)
+{
+ TpBaseCallStream *base = (TpBaseCallStream *) self;
+ TpSendingState local_sending_state =
+ tp_base_call_stream_get_local_sending_state (base);
+ TpSendingState remote_sending_state =
+ tp_base_call_stream_get_remote_sending_state (base, self->priv->handle);
+
+ /* In some protocols, streams cannot be neither sending nor receiving, so
+ * if a stream is set to TP_MEDIA_STREAM_DIRECTION_NONE, this is equivalent
+ * to removing it. (This is true in XMPP, for instance.)
+ *
+ * However, for this example we'll emulate a protocol where streams can be
+ * directionless.
+ */
+
+ if (local_send)
+ {
+ g_message ("%s: SIGNALLING: send: Please start sending me media",
+ tp_base_call_stream_get_object_path (base));
+
+ if (local_sending_state == TP_SENDING_STATE_NONE)
+ {
+ /* ask the user for permission */
+ tp_base_call_stream_update_local_sending_state (base,
+ TP_SENDING_STATE_PENDING_SEND, 0,
+ TP_CALL_STATE_CHANGE_REASON_UNKNOWN,
+ "", "");
+ }
+ else
+ {
+ /* nothing to do, we're already sending (or asking the user for
+ * permission to do so) on that stream */
+ }
+ }
+ else
+ {
+ g_message ("%s: SIGNALLING: receive: Please stop sending me media",
+ tp_base_call_stream_get_object_path (base));
+ g_message ("%s: SIGNALLING: reply: OK!",
+ tp_base_call_stream_get_object_path (base));
+
+ if (local_sending_state == TP_SENDING_STATE_SENDING)
+ {
+ g_message ("%s: MEDIA: no longer sending media to peer",
+ tp_base_call_stream_get_object_path (base));
+
+ tp_base_call_stream_update_local_sending_state (base,
+ TP_SENDING_STATE_NONE, 0,
+ TP_CALL_STATE_CHANGE_REASON_UNKNOWN,
+ "", "");
+ }
+ else if (local_sending_state == TP_SENDING_STATE_PENDING_SEND)
+ {
+ tp_base_call_stream_update_local_sending_state (base,
+ TP_SENDING_STATE_NONE, 0,
+ TP_CALL_STATE_CHANGE_REASON_UNKNOWN,
+ "", "");
+ }
+ else
+ {
+ /* nothing to do, we're not sending on that stream anyway */
+ }
+ }
+
+ if (remote_send)
+ {
+ g_message ("%s: SIGNALLING: receive: I will now send you media",
+ tp_base_call_stream_get_object_path (base));
+
+ if (remote_sending_state != TP_SENDING_STATE_SENDING)
+ {
+ tp_base_call_stream_update_remote_sending_state (
+ (TpBaseCallStream *) self,
+ self->priv->handle, TP_SENDING_STATE_SENDING, 0,
+ TP_CALL_STATE_CHANGE_REASON_UNKNOWN, "", "");
+ }
+ }
+ else
+ {
+ if (remote_sending_state == TP_SENDING_STATE_PENDING_SEND)
+ {
+ g_message ("%s: SIGNALLING: receive: No, I refuse to send you media",
+ tp_base_call_stream_get_object_path (base));
+
+ tp_base_call_stream_update_remote_sending_state (
+ (TpBaseCallStream *) self,
+ self->priv->handle, TP_SENDING_STATE_NONE, 0,
+ TP_CALL_STATE_CHANGE_REASON_UNKNOWN, "", "");
+ }
+ else if (remote_sending_state == TP_SENDING_STATE_SENDING)
+ {
+ g_message ("%s: SIGNALLING: receive: I will no longer send media",
+ tp_base_call_stream_get_object_path (base));
+
+ tp_base_call_stream_update_remote_sending_state (
+ (TpBaseCallStream *) self,
+ self->priv->handle, TP_SENDING_STATE_NONE, 0,
+ TP_CALL_STATE_CHANGE_REASON_UNKNOWN, "", "");
+ }
+ }
+}
+
+static gboolean
+stream_set_sending (TpBaseCallStream *base,
+ gboolean sending,
+ GError **error)
+{
+ ExampleCallStream *self = EXAMPLE_CALL_STREAM (base);
+ TpSendingState remote_sending_state =
+ tp_base_call_stream_get_remote_sending_state (base, self->priv->handle);
+
+ example_call_stream_change_direction (self, sending,
+ (remote_sending_state == TP_SENDING_STATE_SENDING));
+
+ return TRUE;
+}
+
+static gboolean
+stream_request_receiving (TpBaseCallStream *base,
+ TpHandle contact,
+ gboolean receive,
+ GError **error)
+{
+ ExampleCallStream *self = EXAMPLE_CALL_STREAM (base);
+ TpSendingState local_sending_state =
+ tp_base_call_stream_get_local_sending_state (base);
+
+ /* This is the only member */
+ g_assert (contact == self->priv->handle);
+
+ example_call_stream_change_direction (self,
+ (local_sending_state == TP_SENDING_STATE_SENDING),
+ receive);
+
+ return TRUE;
+}
diff --git a/examples/cm/call/call-stream.h b/examples/cm/call/call-stream.h
new file mode 100644
index 000000000..0b8b08dc5
--- /dev/null
+++ b/examples/cm/call/call-stream.h
@@ -0,0 +1,80 @@
+/*
+ * call-stream.h - header for an example stream
+ *
+ * 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_CALL_STREAM_H
+#define EXAMPLE_CALL_STREAM_H
+
+#include <glib-object.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ExampleCallStream ExampleCallStream;
+typedef struct _ExampleCallStreamPrivate
+ ExampleCallStreamPrivate;
+
+typedef struct _ExampleCallStreamClass
+ ExampleCallStreamClass;
+typedef struct _ExampleCallStreamClassPrivate
+ ExampleCallStreamClassPrivate;
+
+GType example_call_stream_get_type (void);
+
+#define EXAMPLE_TYPE_CALL_STREAM \
+ (example_call_stream_get_type ())
+#define EXAMPLE_CALL_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXAMPLE_TYPE_CALL_STREAM, \
+ ExampleCallStream))
+#define EXAMPLE_CALL_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), EXAMPLE_TYPE_CALL_STREAM, \
+ ExampleCallStreamClass))
+#define EXAMPLE_IS_CALL_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXAMPLE_TYPE_CALL_STREAM))
+#define EXAMPLE_IS_CALL_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), EXAMPLE_TYPE_CALL_STREAM))
+#define EXAMPLE_CALL_STREAM_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), EXAMPLE_TYPE_CALL_STREAM, \
+ ExampleCallStreamClass))
+
+struct _ExampleCallStreamClass {
+ TpBaseMediaCallStreamClass parent_class;
+
+ ExampleCallStreamClassPrivate *priv;
+};
+
+struct _ExampleCallStream {
+ TpBaseMediaCallStream parent;
+
+ ExampleCallStreamPrivate *priv;
+};
+
+void example_call_stream_accept_proposed_direction (ExampleCallStream *self);
+void example_call_stream_connect (ExampleCallStream *self);
+
+/* This controls receiving emulated network events, so it wouldn't exist in
+ * a real connection manager */
+void example_call_stream_simulate_contact_agreed_to_send (
+ ExampleCallStream *self);
+
+G_END_DECLS
+
+#endif
diff --git a/examples/cm/callable/connection-manager.c b/examples/cm/call/cm.c
index 3ec4d788c..5e42d97d3 100644
--- a/examples/cm/callable/connection-manager.c
+++ b/examples/cm/call/cm.c
@@ -21,7 +21,7 @@
#include "config.h"
-#include "connection-manager.h"
+#include "cm.h"
#include <dbus/dbus-glib.h>
@@ -31,38 +31,37 @@
#include "conn.h"
#include "protocol.h"
-G_DEFINE_TYPE (ExampleCallableConnectionManager,
- example_callable_connection_manager,
+G_DEFINE_TYPE (ExampleCallConnectionManager,
+ example_call_connection_manager,
TP_TYPE_BASE_CONNECTION_MANAGER)
-struct _ExampleCallableConnectionManagerPrivate
+struct _ExampleCallConnectionManagerPrivate
{
int dummy;
};
static void
-example_callable_connection_manager_init (
- ExampleCallableConnectionManager *self)
+example_call_connection_manager_init (ExampleCallConnectionManager *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- EXAMPLE_TYPE_CALLABLE_CONNECTION_MANAGER,
- ExampleCallableConnectionManagerPrivate);
+ EXAMPLE_TYPE_CALL_CONNECTION_MANAGER,
+ ExampleCallConnectionManagerPrivate);
}
static void
-example_callable_connection_manager_constructed (GObject *object)
+example_call_connection_manager_constructed (GObject *object)
{
- ExampleCallableConnectionManager *self =
- EXAMPLE_CALLABLE_CONNECTION_MANAGER (object);
+ ExampleCallConnectionManager *self =
+ EXAMPLE_CALL_CONNECTION_MANAGER (object);
TpBaseConnectionManager *base = (TpBaseConnectionManager *) self;
void (*constructed) (GObject *) =
- ((GObjectClass *) example_callable_connection_manager_parent_class)->constructed;
+ ((GObjectClass *) example_call_connection_manager_parent_class)->constructed;
TpBaseProtocol *protocol;
if (constructed != NULL)
constructed (object);
- protocol = g_object_new (EXAMPLE_TYPE_CALLABLE_PROTOCOL,
+ protocol = g_object_new (EXAMPLE_TYPE_CALL_PROTOCOL,
"name", "example",
NULL);
tp_base_connection_manager_add_protocol (base, protocol);
@@ -70,16 +69,16 @@ example_callable_connection_manager_constructed (GObject *object)
}
static void
-example_callable_connection_manager_class_init (
- ExampleCallableConnectionManagerClass *klass)
+example_call_connection_manager_class_init (
+ ExampleCallConnectionManagerClass *klass)
{
GObjectClass *object_class = (GObjectClass *) klass;
TpBaseConnectionManagerClass *base_class =
(TpBaseConnectionManagerClass *) klass;
g_type_class_add_private (klass,
- sizeof (ExampleCallableConnectionManagerPrivate));
+ sizeof (ExampleCallConnectionManagerPrivate));
- object_class->constructed = example_callable_connection_manager_constructed;
- base_class->cm_dbus_name = "example_callable";
+ object_class->constructed = example_call_connection_manager_constructed;
+ base_class->cm_dbus_name = "example_call";
}
diff --git a/examples/cm/call/cm.h b/examples/cm/call/cm.h
new file mode 100644
index 000000000..275abb229
--- /dev/null
+++ b/examples/cm/call/cm.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_CALL_CM_H
+#define EXAMPLE_CALL_CM_H
+
+#include <glib-object.h>
+#include <telepathy-glib/base-connection-manager.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ExampleCallConnectionManager
+ ExampleCallConnectionManager;
+typedef struct _ExampleCallConnectionManagerPrivate
+ ExampleCallConnectionManagerPrivate;
+
+typedef struct _ExampleCallConnectionManagerClass
+ ExampleCallConnectionManagerClass;
+typedef struct _ExampleCallConnectionManagerClassPrivate
+ ExampleCallConnectionManagerClassPrivate;
+
+struct _ExampleCallConnectionManagerClass {
+ TpBaseConnectionManagerClass parent_class;
+
+ ExampleCallConnectionManagerClassPrivate *priv;
+};
+
+struct _ExampleCallConnectionManager {
+ TpBaseConnectionManager parent;
+
+ ExampleCallConnectionManagerPrivate *priv;
+};
+
+GType example_call_connection_manager_get_type (void);
+
+/* TYPE MACROS */
+#define EXAMPLE_TYPE_CALL_CONNECTION_MANAGER \
+ (example_call_connection_manager_get_type ())
+#define EXAMPLE_CALL_CONNECTION_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), EXAMPLE_TYPE_CALL_CONNECTION_MANAGER, \
+ ExampleCallConnectionManager))
+#define EXAMPLE_CALL_CONNECTION_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), EXAMPLE_TYPE_CALL_CONNECTION_MANAGER, \
+ ExampleCallConnectionManagerClass))
+#define EXAMPLE_IS_CALL_CONNECTION_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), EXAMPLE_TYPE_CALL_CONNECTION_MANAGER))
+#define EXAMPLE_IS_CALL_CONNECTION_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), EXAMPLE_TYPE_CALL_CONNECTION_MANAGER))
+#define EXAMPLE_CALL_CONNECTION_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), EXAMPLE_TYPE_CALL_CONNECTION_MANAGER, \
+ ExampleCallConnectionManagerClass))
+
+G_END_DECLS
+
+#endif
diff --git a/examples/cm/callable/conn.c b/examples/cm/call/conn.c
index f29d80925..2b7503c16 100644
--- a/examples/cm/callable/conn.c
+++ b/examples/cm/call/conn.c
@@ -29,11 +29,11 @@
#include <telepathy-glib/handle-repo-dynamic.h>
#include <telepathy-glib/handle-repo-static.h>
-#include "media-manager.h"
+#include "call-manager.h"
#include "protocol.h"
-G_DEFINE_TYPE_WITH_CODE (ExampleCallableConnection,
- example_callable_connection,
+G_DEFINE_TYPE_WITH_CODE (ExampleCallConnection,
+ example_call_connection,
TP_TYPE_BASE_CONNECTION,
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS,
tp_contacts_mixin_iface_init);
@@ -57,7 +57,7 @@ enum
static guint signals[N_SIGNALS] = { 0 };
-struct _ExampleCallableConnectionPrivate
+struct _ExampleCallConnectionPrivate
{
gchar *account;
guint simulation_delay;
@@ -66,11 +66,11 @@ struct _ExampleCallableConnectionPrivate
};
static void
-example_callable_connection_init (ExampleCallableConnection *self)
+example_call_connection_init (ExampleCallConnection *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- EXAMPLE_TYPE_CALLABLE_CONNECTION,
- ExampleCallableConnectionPrivate);
+ EXAMPLE_TYPE_CALL_CONNECTION,
+ ExampleCallConnectionPrivate);
self->priv->away = FALSE;
self->priv->presence_message = g_strdup ("");
}
@@ -81,7 +81,7 @@ get_property (GObject *object,
GValue *value,
GParamSpec *spec)
{
- ExampleCallableConnection *self = EXAMPLE_CALLABLE_CONNECTION (object);
+ ExampleCallConnection *self = EXAMPLE_CALL_CONNECTION (object);
switch (property_id)
{
@@ -100,11 +100,11 @@ get_property (GObject *object,
static void
set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *spec)
+ guint property_id,
+ const GValue *value,
+ GParamSpec *spec)
{
- ExampleCallableConnection *self = EXAMPLE_CALLABLE_CONNECTION (object);
+ ExampleCallConnection *self = EXAMPLE_CALL_CONNECTION (object);
switch (property_id)
{
@@ -125,32 +125,32 @@ set_property (GObject *object,
static void
finalize (GObject *object)
{
- ExampleCallableConnection *self = EXAMPLE_CALLABLE_CONNECTION (object);
+ ExampleCallConnection *self = EXAMPLE_CALL_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);
+ G_OBJECT_CLASS (example_call_connection_parent_class)->finalize (object);
}
static gchar *
get_unique_connection_name (TpBaseConnection *conn)
{
- ExampleCallableConnection *self = EXAMPLE_CALLABLE_CONNECTION (conn);
+ ExampleCallConnection *self = EXAMPLE_CALL_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)
+static gchar *
+example_call_normalize_contact (TpHandleRepoIface *repo,
+ const gchar *id,
+ gpointer context,
+ GError **error)
{
gchar *normal = NULL;
- if (example_callable_protocol_check_contact_id (id, &normal, error))
+ if (example_call_protocol_check_contact_id (id, &normal, error))
return normal;
else
return NULL;
@@ -158,20 +158,20 @@ example_callable_normalize_contact (TpHandleRepoIface *repo,
static void
create_handle_repos (TpBaseConnection *conn,
- TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES])
+ 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);
+ (TP_HANDLE_TYPE_CONTACT, example_call_normalize_contact, NULL);
}
static GPtrArray *
create_channel_managers (TpBaseConnection *conn)
{
- ExampleCallableConnection *self = EXAMPLE_CALLABLE_CONNECTION (conn);
+ ExampleCallConnection *self = EXAMPLE_CALL_CONNECTION (conn);
GPtrArray *ret = g_ptr_array_sized_new (1);
g_ptr_array_add (ret,
- g_object_new (EXAMPLE_TYPE_CALLABLE_MEDIA_MANAGER,
+ g_object_new (EXAMPLE_TYPE_CALL_MANAGER,
"connection", conn,
"simulation-delay", self->priv->simulation_delay,
NULL));
@@ -181,9 +181,9 @@ create_channel_managers (TpBaseConnection *conn)
static gboolean
start_connecting (TpBaseConnection *conn,
- GError **error)
+ GError **error)
{
- ExampleCallableConnection *self = EXAMPLE_CALLABLE_CONNECTION (conn);
+ ExampleCallConnection *self = EXAMPLE_CALL_CONNECTION (conn);
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn,
TP_HANDLE_TYPE_CONTACT);
@@ -217,23 +217,23 @@ constructed (GObject *object)
{
TpBaseConnection *base = TP_BASE_CONNECTION (object);
void (*chain_up) (GObject *) =
- G_OBJECT_CLASS (example_callable_connection_parent_class)->constructed;
+ G_OBJECT_CLASS (example_call_connection_parent_class)->constructed;
if (chain_up != NULL)
chain_up (object);
tp_contacts_mixin_init (object,
- G_STRUCT_OFFSET (ExampleCallableConnection, contacts_mixin));
+ G_STRUCT_OFFSET (ExampleCallConnection, contacts_mixin));
tp_base_connection_register_with_contacts_mixin (base);
tp_presence_mixin_init (object,
- G_STRUCT_OFFSET (ExampleCallableConnection, presence_mixin));
+ G_STRUCT_OFFSET (ExampleCallConnection, presence_mixin));
tp_presence_mixin_simple_presence_register_with_contacts_mixin (object);
}
static gboolean
status_available (GObject *object,
- guint index_)
+ guint index_)
{
TpBaseConnection *base = TP_BASE_CONNECTION (object);
@@ -245,11 +245,11 @@ status_available (GObject *object,
static GHashTable *
get_contact_statuses (GObject *object,
- const GArray *contacts,
- GError **error)
+ const GArray *contacts,
+ GError **error)
{
- ExampleCallableConnection *self =
- EXAMPLE_CALLABLE_CONNECTION (object);
+ ExampleCallConnection *self =
+ EXAMPLE_CALL_CONNECTION (object);
TpBaseConnection *base = TP_BASE_CONNECTION (object);
guint i;
GHashTable *result = g_hash_table_new_full (g_direct_hash, g_direct_equal,
@@ -258,7 +258,7 @@ get_contact_statuses (GObject *object,
for (i = 0; i < contacts->len; i++)
{
TpHandle contact = g_array_index (contacts, guint, i);
- ExampleCallablePresence presence;
+ ExampleCallPresence presence;
GHashTable *parameters;
parameters = g_hash_table_new_full (g_str_hash,
@@ -268,8 +268,8 @@ get_contact_statuses (GObject *object,
* 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);
+ presence = (self->priv->away ? EXAMPLE_CALL_PRESENCE_AWAY
+ : EXAMPLE_CALL_PRESENCE_AVAILABLE);
if (self->priv->presence_message[0] != '\0')
g_hash_table_insert (parameters, "message",
@@ -277,7 +277,7 @@ get_contact_statuses (GObject *object,
}
else
{
- presence = EXAMPLE_CALLABLE_PRESENCE_AVAILABLE;
+ presence = EXAMPLE_CALL_PRESENCE_AVAILABLE;
}
g_hash_table_insert (result, GUINT_TO_POINTER (contact),
@@ -290,11 +290,11 @@ get_contact_statuses (GObject *object,
static gboolean
set_own_status (GObject *object,
- const TpPresenceStatus *status,
- GError **error)
+ const TpPresenceStatus *status,
+ GError **error)
{
- ExampleCallableConnection *self =
- EXAMPLE_CALLABLE_CONNECTION (object);
+ ExampleCallConnection *self =
+ EXAMPLE_CALL_CONNECTION (object);
TpBaseConnection *base = TP_BASE_CONNECTION (object);
GHashTable *presences;
const gchar *message = "";
@@ -312,7 +312,7 @@ set_own_status (GObject *object,
}
}
- if (status->index == EXAMPLE_CALLABLE_PRESENCE_AWAY)
+ if (status->index == EXAMPLE_CALL_PRESENCE_AWAY)
{
if (self->priv->away && !tp_strdiff (message,
self->priv->presence_message))
@@ -352,7 +352,7 @@ static const TpPresenceStatusOptionalArgumentSpec can_have_message[] = {
{ NULL }
};
-/* Must be kept in sync with ExampleCallablePresence enum in header */
+/* Must be kept in sync with ExampleCallPresence enum in header */
static const TpPresenceStatusSpec presence_statuses[] = {
{ "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE, FALSE, NULL },
{ "unknown", TP_CONNECTION_PRESENCE_TYPE_UNKNOWN, FALSE, NULL },
@@ -371,7 +371,7 @@ static const gchar *interfaces_always_present[] = {
NULL };
const gchar * const *
-example_callable_connection_get_possible_interfaces (void)
+example_call_connection_get_possible_interfaces (void)
{
/* in this example CM we don't have any extra interfaces that are sometimes,
* but not always, present */
@@ -379,8 +379,8 @@ example_callable_connection_get_possible_interfaces (void)
}
static void
-example_callable_connection_class_init (
- ExampleCallableConnectionClass *klass)
+example_call_connection_class_init (
+ ExampleCallConnectionClass *klass)
{
TpBaseConnectionClass *base_class = (TpBaseConnectionClass *) klass;
GObjectClass *object_class = (GObjectClass *) klass;
@@ -391,7 +391,7 @@ example_callable_connection_class_init (
object_class->constructed = constructed;
object_class->finalize = finalize;
g_type_class_add_private (klass,
- sizeof (ExampleCallableConnectionPrivate));
+ sizeof (ExampleCallConnectionPrivate));
base_class->create_handle_repos = create_handle_repos;
base_class->get_unique_connection_name = get_unique_connection_name;
@@ -412,7 +412,7 @@ example_callable_connection_class_init (
g_object_class_install_property (object_class, PROP_SIMULATION_DELAY,
param_spec);
- /* Used in the media manager, to simulate an incoming call when we become
+ /* Used in the call manager, to simulate an incoming call when we become
* available */
signals[SIGNAL_AVAILABLE] = g_signal_new ("available",
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
@@ -420,9 +420,9 @@ example_callable_connection_class_init (
G_TYPE_NONE, 1, G_TYPE_STRING);
tp_contacts_mixin_class_init (object_class,
- G_STRUCT_OFFSET (ExampleCallableConnectionClass, contacts_mixin));
+ G_STRUCT_OFFSET (ExampleCallConnectionClass, contacts_mixin));
tp_presence_mixin_class_init (object_class,
- G_STRUCT_OFFSET (ExampleCallableConnectionClass, presence_mixin),
+ G_STRUCT_OFFSET (ExampleCallConnectionClass, 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/call/conn.h b/examples/cm/call/conn.h
new file mode 100644
index 000000000..1ad22ae3a
--- /dev/null
+++ b/examples/cm/call/conn.h
@@ -0,0 +1,77 @@
+/*
+ * 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_CALL_CONN_H
+#define EXAMPLE_CALL_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 _ExampleCallConnection ExampleCallConnection;
+typedef struct _ExampleCallConnectionPrivate
+ ExampleCallConnectionPrivate;
+
+typedef struct _ExampleCallConnectionClass ExampleCallConnectionClass;
+typedef struct _ExampleCallConnectionClassPrivate
+ ExampleCallConnectionClassPrivate;
+
+struct _ExampleCallConnectionClass {
+ TpBaseConnectionClass parent_class;
+ TpPresenceMixinClass presence_mixin;
+ TpContactsMixinClass contacts_mixin;
+
+ ExampleCallConnectionClassPrivate *priv;
+};
+
+struct _ExampleCallConnection {
+ TpBaseConnection parent;
+ TpPresenceMixin presence_mixin;
+ TpContactsMixin contacts_mixin;
+
+ ExampleCallConnectionPrivate *priv;
+};
+
+GType example_call_connection_get_type (void);
+
+#define EXAMPLE_TYPE_CALL_CONNECTION \
+ (example_call_connection_get_type ())
+#define EXAMPLE_CALL_CONNECTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), EXAMPLE_TYPE_CALL_CONNECTION, \
+ ExampleCallConnection))
+#define EXAMPLE_CALL_CONNECTION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), EXAMPLE_TYPE_CALL_CONNECTION, \
+ ExampleCallConnectionClass))
+#define EXAMPLE_IS_CALL_CONNECTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), EXAMPLE_TYPE_CALL_CONNECTION))
+#define EXAMPLE_IS_CALL_CONNECTION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), EXAMPLE_TYPE_CALL_CONNECTION))
+#define EXAMPLE_CALL_CONNECTION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), EXAMPLE_TYPE_CALL_CONNECTION, \
+ ExampleCallConnectionClass))
+
+/* Must be kept in sync with the array presence_statuses in conn.c */
+typedef enum {
+ EXAMPLE_CALL_PRESENCE_OFFLINE = 0,
+ EXAMPLE_CALL_PRESENCE_UNKNOWN,
+ EXAMPLE_CALL_PRESENCE_ERROR,
+ EXAMPLE_CALL_PRESENCE_AWAY,
+ EXAMPLE_CALL_PRESENCE_AVAILABLE
+} ExampleCallPresence;
+
+const gchar * const *example_call_connection_get_possible_interfaces (void);
+
+G_END_DECLS
+
+#endif
diff --git a/examples/cm/call/example_call.manager b/examples/cm/call/example_call.manager
new file mode 100644
index 000000000..b83bd93d5
--- /dev/null
+++ b/examples/cm/call/example_call.manager
@@ -0,0 +1,25 @@
+[ConnectionManager]
+Interfaces=
+
+[Protocol example]
+Interfaces=
+ConnectionInterfaces=org.freedesktop.Telepathy.Connection.Interface.Requests;org.freedesktop.Telepathy.Connection.Interface.Contacts;org.freedesktop.Telepathy.Connection.Interface.Presence;org.freedesktop.Telepathy.Connection.Interface.SimplePresence;
+param-account=s required register
+param-simulation-delay=u
+default-simulation-delay=1000
+RequestableChannelClasses=audio;video;
+VCardField=x-telepathy-example
+EnglishName=Example with Call channels
+Icon=face-smile
+
+[audio]
+org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.Call.DRAFT
+org.freedesktop.Telepathy.Channel.TargetHandleType u=1
+org.freedesktop.Telepathy.Channel.Type.Call.DRAFT.InitialAudio b=1
+allowed=org.freedesktop.Telepathy.Channel.TargetHandle;org.freedesktop.Telepathy.Channel.TargetID;org.freedesktop.Telepathy.Channel.Type.Call.DRAFT.InitialVideo;
+
+[video]
+org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.Call.DRAFT
+org.freedesktop.Telepathy.Channel.TargetHandleType u=1
+org.freedesktop.Telepathy.Channel.Type.Call.DRAFT.InitialVideo b=1
+allowed=org.freedesktop.Telepathy.Channel.TargetHandle;org.freedesktop.Telepathy.Channel.TargetID;org.freedesktop.Telepathy.Channel.Type.Call.DRAFT.InitialAudio;
diff --git a/examples/cm/callable/main.c b/examples/cm/call/main.c
index ea0b1715b..a25936e1b 100644
--- a/examples/cm/callable/main.c
+++ b/examples/cm/call/main.c
@@ -21,16 +21,18 @@
#include "config.h"
+#include "config.h"
+
#include <telepathy-glib/debug.h>
#include <telepathy-glib/run.h>
-#include "connection-manager.h"
+#include "cm.h"
static TpBaseConnectionManager *
construct_cm (void)
{
return (TpBaseConnectionManager *) g_object_new (
- EXAMPLE_TYPE_CALLABLE_CONNECTION_MANAGER,
+ EXAMPLE_TYPE_CALL_CONNECTION_MANAGER,
NULL);
}
@@ -49,6 +51,10 @@ main (int argc,
tp_debug_set_persistent (TRUE);
#endif
- return tp_run_connection_manager ("telepathy-example-cm-callable",
+ /* strictly speaking, this is only necessary for client code, but it's
+ * harmless here */
+ g_type_init ();
+
+ return tp_run_connection_manager ("telepathy-example-cm-call",
VERSION, construct_cm, argc, argv);
}
diff --git a/examples/cm/callable/protocol.c b/examples/cm/call/protocol.c
index cf752e3d7..26540ddcc 100644
--- a/examples/cm/callable/protocol.c
+++ b/examples/cm/call/protocol.c
@@ -14,21 +14,21 @@
#include <telepathy-glib/telepathy-glib.h>
+#include "call-manager.h"
#include "conn.h"
-#include "media-manager.h"
-G_DEFINE_TYPE (ExampleCallableProtocol,
- example_callable_protocol,
+G_DEFINE_TYPE (ExampleCallProtocol,
+ example_call_protocol,
TP_TYPE_BASE_PROTOCOL)
static void
-example_callable_protocol_init (
- ExampleCallableProtocol *self)
+example_call_protocol_init (
+ ExampleCallProtocol *self)
{
}
gboolean
-example_callable_protocol_check_contact_id (const gchar *id,
+example_call_protocol_check_contact_id (const gchar *id,
gchar **normal,
GError **error)
{
@@ -54,10 +54,10 @@ account_param_filter (const TpCMParamSpec *paramspec,
{
const gchar *id = g_value_get_string (value);
- return example_callable_protocol_check_contact_id (id, NULL, error);
+ return example_call_protocol_check_contact_id (id, NULL, error);
}
-static const TpCMParamSpec example_callable_example_params[] = {
+static const TpCMParamSpec example_call_example_params[] = {
{ "account", "s", G_TYPE_STRING,
TP_CONN_MGR_PARAM_FLAG_REQUIRED | TP_CONN_MGR_PARAM_FLAG_REGISTER,
NULL, /* no default */
@@ -78,7 +78,7 @@ static const TpCMParamSpec example_callable_example_params[] = {
static const TpCMParamSpec *
get_parameters (TpBaseProtocol *self)
{
- return example_callable_example_params;
+ return example_call_example_params;
}
static TpBaseConnection *
@@ -86,7 +86,7 @@ new_connection (TpBaseProtocol *protocol,
GHashTable *asv,
GError **error)
{
- ExampleCallableConnection *conn;
+ ExampleCallConnection *conn;
const gchar *account;
guint sim_delay;
@@ -96,8 +96,8 @@ new_connection (TpBaseProtocol *protocol,
sim_delay = tp_asv_get_uint32 (asv, "simulation-delay", NULL);
- conn = EXAMPLE_CALLABLE_CONNECTION (
- g_object_new (EXAMPLE_TYPE_CALLABLE_CONNECTION,
+ conn = EXAMPLE_CALL_CONNECTION (
+ g_object_new (EXAMPLE_TYPE_CALL_CONNECTION,
"account", account,
"protocol", tp_base_protocol_get_name (protocol),
"simulation-delay", sim_delay,
@@ -113,7 +113,7 @@ normalize_contact (TpBaseProtocol *self G_GNUC_UNUSED,
{
gchar *normal;
- if (example_callable_protocol_check_contact_id (contact, &normal, error))
+ if (example_call_protocol_check_contact_id (contact, &normal, error))
return normal;
else
return NULL;
@@ -151,12 +151,12 @@ get_connection_details (TpBaseProtocol *self G_GNUC_UNUSED,
if (connection_interfaces != NULL)
{
*connection_interfaces = g_strdupv (
- (GStrv) example_callable_connection_get_possible_interfaces ());
+ (GStrv) example_call_connection_get_possible_interfaces ());
}
if (channel_managers != NULL)
{
- GType types[] = { EXAMPLE_TYPE_CALLABLE_MEDIA_MANAGER, G_TYPE_INVALID };
+ GType types[] = { EXAMPLE_TYPE_CALL_MANAGER, G_TYPE_INVALID };
*channel_managers = g_memdup (types, sizeof (types));
}
@@ -165,15 +165,15 @@ get_connection_details (TpBaseProtocol *self G_GNUC_UNUSED,
*icon_name = g_strdup ("face-smile");
if (english_name != NULL)
- *english_name = g_strdup ("Example with StreamedMedia calls");
+ *english_name = g_strdup ("Example with Call channels");
if (vcard_field != NULL)
*vcard_field = g_strdup ("x-telepathy-example");
}
static void
-example_callable_protocol_class_init (
- ExampleCallableProtocolClass *klass)
+example_call_protocol_class_init (
+ ExampleCallProtocolClass *klass)
{
TpBaseProtocolClass *base_class =
(TpBaseProtocolClass *) klass;
diff --git a/examples/cm/call/protocol.h b/examples/cm/call/protocol.h
new file mode 100644
index 000000000..68d2acd7c
--- /dev/null
+++ b/examples/cm/call/protocol.h
@@ -0,0 +1,64 @@
+/*
+ * protocol.h - header for an example Protocol
+ * Copyright © 2007-2010 Collabora Ltd.
+ *
+ * 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_CALL_PROTOCOL_H
+#define EXAMPLE_CALL_PROTOCOL_H
+
+#include <glib-object.h>
+#include <telepathy-glib/base-protocol.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ExampleCallProtocol ExampleCallProtocol;
+typedef struct _ExampleCallProtocolPrivate ExampleCallProtocolPrivate;
+typedef struct _ExampleCallProtocolClass ExampleCallProtocolClass;
+typedef struct _ExampleCallProtocolClassPrivate ExampleCallProtocolClassPrivate;
+
+struct _ExampleCallProtocolClass {
+ TpBaseProtocolClass parent_class;
+
+ ExampleCallProtocolClassPrivate *priv;
+};
+
+struct _ExampleCallProtocol {
+ TpBaseProtocol parent;
+
+ ExampleCallProtocolPrivate *priv;
+};
+
+GType example_call_protocol_get_type (void);
+
+#define EXAMPLE_TYPE_CALL_PROTOCOL \
+ (example_call_protocol_get_type ())
+#define EXAMPLE_CALL_PROTOCOL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ EXAMPLE_TYPE_CALL_PROTOCOL, \
+ ExampleCallProtocol))
+#define EXAMPLE_CALL_PROTOCOL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ EXAMPLE_TYPE_CALL_PROTOCOL, \
+ ExampleCallProtocolClass))
+#define EXAMPLE_IS_CALL_PROTOCOL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ EXAMPLE_TYPE_CALL_PROTOCOL))
+#define EXAMPLE_IS_CALL_PROTOCOL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ EXAMPLE_TYPE_CALL_PROTOCOL))
+#define EXAMPLE_CALL_PROTOCOL_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ EXAMPLE_TYPE_CALL_PROTOCOL, \
+ ExampleCallProtocolClass))
+
+gboolean example_call_protocol_check_contact_id (const gchar *id,
+ gchar **normal,
+ GError **error);
+
+G_END_DECLS
+
+#endif
diff --git a/examples/cm/callable/conn.h b/examples/cm/callable/conn.h
deleted file mode 100644
index eee9d988c..000000000
--- a/examples/cm/callable/conn.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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;
-
-const gchar * const * example_callable_connection_get_possible_interfaces (
- void);
-
-G_END_DECLS
-
-#endif
diff --git a/examples/cm/callable/connection-manager.h b/examples/cm/callable/connection-manager.h
deleted file mode 100644
index 5d854cb1c..000000000
--- a/examples/cm/callable/connection-manager.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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/example_callable.manager b/examples/cm/callable/example_callable.manager
deleted file mode 100644
index 0caf732a7..000000000
--- a/examples/cm/callable/example_callable.manager
+++ /dev/null
@@ -1,19 +0,0 @@
-[ConnectionManager]
-Interfaces=
-
-[Protocol example]
-Interfaces=
-ConnectionInterfaces=org.freedesktop.Telepathy.Connection.Interface.Requests;org.freedesktop.Telepathy.Connection.Interface.Contacts;org.freedesktop.Telepathy.Connection.Interface.Presence;org.freedesktop.Telepathy.Connection.Interface.SimplePresence;
-param-account=s required register
-param-simulation-delay=u
-default-simulation-delay=1000
-RequestableChannelClasses=streamedmedia;
-VCardField=x-telepathy-example
-EnglishName=Example with StreamedMedia calls
-Icon=face-smile
-
-[streamedmedia]
-org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.StreamedMedia
-org.freedesktop.Telepathy.Channel.TargetHandleType u=1
-allowed=org.freedesktop.Telepathy.Channel.TargetHandle;org.freedesktop.Telepathy.Channel.TargetID;
-
diff --git a/examples/cm/callable/media-channel.c b/examples/cm/callable/media-channel.c
deleted file mode 100644
index a9920668b..000000000
--- a/examples/cm/callable/media-channel.c
+++ /dev/null
@@ -1,1244 +0,0 @@
-/*
- * 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 "config.h"
-
-#include "media-channel.h"
-
-#include "media-stream.h"
-
-#include <string.h>
-
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/gtypes.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 hold_iface_init (gpointer iface, gpointer data);
-static void dtmf_iface_init (gpointer iface, gpointer data);
-
-G_DEFINE_TYPE_WITH_CODE (ExampleCallableMediaChannel,
- example_callable_media_channel,
- TP_TYPE_BASE_CHANNEL,
- 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_SVC_CHANNEL_INTERFACE_HOLD,
- hold_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_DTMF,
- dtmf_iface_init);)
-
-enum
-{
- PROP_SIMULATION_DELAY = 1,
- PROP_INITIAL_AUDIO,
- PROP_INITIAL_VIDEO,
- N_PROPS
-};
-
-enum
-{
- SIGNAL_CALL_TERMINATED,
- N_SIGNALS
-};
-
-typedef enum {
- PROGRESS_NONE,
- PROGRESS_CALLING,
- PROGRESS_ACTIVE,
- PROGRESS_ENDED
-} ExampleCallableCallProgress;
-
-static guint signals[N_SIGNALS] = { 0 };
-
-struct _ExampleCallableMediaChannelPrivate
-{
- ExampleCallableCallProgress progress;
-
- guint simulation_delay;
-
- guint next_stream_id;
-
- GHashTable *streams;
-
- guint hold_state;
- guint hold_state_reason;
-
- gboolean initial_audio;
- gboolean initial_video;
- gboolean disposed;
-};
-
-static const char * example_callable_media_channel_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- TP_IFACE_CHANNEL_INTERFACE_HOLD,
- TP_IFACE_CHANNEL_INTERFACE_DTMF,
- NULL
-};
-
-static void
-example_callable_media_channel_init (ExampleCallableMediaChannel *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- EXAMPLE_TYPE_CALLABLE_MEDIA_CHANNEL,
- ExampleCallableMediaChannelPrivate);
-
- self->priv->next_stream_id = 1;
- self->priv->streams = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, g_object_unref);
-
- self->priv->hold_state = TP_LOCAL_HOLD_STATE_UNHELD;
- self->priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE;
-}
-
-static ExampleCallableMediaStream *example_callable_media_channel_add_stream (
- ExampleCallableMediaChannel *self, TpMediaStreamType media_type,
- gboolean locally_requested);
-
-static void
-constructed (GObject *object)
-{
- void (*chain_up) (GObject *) =
- ((GObjectClass *) example_callable_media_channel_parent_class)->constructed;
- ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (object);
- TpBaseChannel *base_chan = TP_BASE_CHANNEL (self);
- TpBaseConnection *connection = tp_base_channel_get_connection (base_chan);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
- (connection, TP_HANDLE_TYPE_CONTACT);
- TpIntset *members;
- TpIntset *local_pending;
- gboolean requested;
-
- if (chain_up != NULL)
- chain_up (object);
-
- tp_base_channel_register (base_chan);
-
- tp_group_mixin_init (object,
- G_STRUCT_OFFSET (ExampleCallableMediaChannel, group),
- contact_repo,
- connection->self_handle);
-
- /* Initially, the channel contains the initiator as a member; they are also
- * the actor for the change that adds any initial members. */
-
- members = tp_intset_new_containing (tp_base_channel_get_initiator (base_chan));
- requested = tp_base_channel_is_requested (base_chan);
-
- if (requested)
- {
- /* Nobody is locally pending. The remote peer will turn up in
- * remote-pending state when we actually contact them, which is done
- * in RequestStreams */
- self->priv->progress = PROGRESS_NONE;
- local_pending = NULL;
- }
- else
- {
- /* This is an incoming call, so the self-handle is locally
- * pending, to indicate that we need to answer. */
- self->priv->progress = PROGRESS_CALLING;
- local_pending = tp_intset_new_containing (connection->self_handle);
- }
-
- tp_group_mixin_change_members (object, "",
- members /* added */,
- NULL /* nobody removed */,
- local_pending, /* added to local-pending */
- NULL /* nobody added to remote-pending */,
- tp_base_channel_get_initiator (base_chan) /* actor */,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (members);
-
- if (local_pending != NULL)
- tp_intset_destroy (local_pending);
-
- /* We don't need to allow adding or removing members to this Group in ways
- * that need flags set, so the only flag we set is to say we support the
- * Properties interface to the Group.
- *
- * It doesn't make sense to add anyone to the Group, since we already know
- * who we're going to call (or were called by). The only call to AddMembers
- * we need to support is to move ourselves from local-pending to member in
- * the incoming call case, and that's always allowed anyway.
- *
- * (Connection managers that support the various backwards-compatible
- * ways to make an outgoing StreamedMedia channel have to support adding the
- * peer to remote-pending, but that has no actual effect other than to
- * obscure what's going on; in this one, there's no need to support that
- * usage.)
- *
- * Similarly, it doesn't make sense to remove anyone from this Group apart
- * from ourselves (to hang up), and removing the SelfHandle is always
- * allowed anyway.
- */
- tp_group_mixin_change_flags (object, TP_CHANNEL_GROUP_FLAG_PROPERTIES, 0);
-
- /* Future versions of telepathy-spec will allow a channel request to
- * say "initially include an audio stream" and/or "initially include a video
- * stream", which would be represented like this; we don't support this
- * usage yet, though, so ExampleCallableMediaManager will never invoke
- * our constructor in this way. */
- g_assert (!(requested && self->priv->initial_audio));
- g_assert (!(requested && self->priv->initial_video));
-
- if (!requested)
- {
- /* the caller has almost certainly asked us for some streams - there's
- * not much point in having a call otherwise */
-
- if (self->priv->initial_audio)
- {
- g_message ("Channel initially has an audio stream");
- example_callable_media_channel_add_stream (self,
- TP_MEDIA_STREAM_TYPE_AUDIO, FALSE);
- }
-
- if (self->priv->initial_video)
- {
- g_message ("Channel initially has a video stream");
- example_callable_media_channel_add_stream (self,
- TP_MEDIA_STREAM_TYPE_VIDEO, FALSE);
- }
- }
-}
-
-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_SIMULATION_DELAY:
- g_value_set_uint (value, self->priv->simulation_delay);
- break;
-
- case PROP_INITIAL_AUDIO:
- g_value_set_boolean (value, self->priv->initial_audio);
- break;
-
- case PROP_INITIAL_VIDEO:
- g_value_set_boolean (value, self->priv->initial_video);
- 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_SIMULATION_DELAY:
- self->priv->simulation_delay = g_value_get_uint (value);
- break;
-
- case PROP_INITIAL_AUDIO:
- self->priv->initial_audio = g_value_get_boolean (value);
- break;
-
- case PROP_INITIAL_VIDEO:
- self->priv->initial_video = g_value_get_boolean (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-example_callable_media_channel_close (ExampleCallableMediaChannel *self,
- TpHandle actor,
- TpChannelGroupChangeReason reason)
-{
- if (self->priv->progress != PROGRESS_ENDED)
- {
- TpIntset *everyone;
-
- self->priv->progress = PROGRESS_ENDED;
-
- if (actor == self->group.self_handle)
- {
- const gchar *send_reason;
-
- /* In a real protocol these would be some sort of real protocol
- * construct, like an XMPP error stanza or a SIP error code */
- switch (reason)
- {
- case TP_CHANNEL_GROUP_CHANGE_REASON_BUSY:
- send_reason = "<user-is-busy/>";
- break;
-
- case TP_CHANNEL_GROUP_CHANGE_REASON_NO_ANSWER:
- send_reason = "<no-answer/>";
- break;
-
- default:
- send_reason = "<call-terminated/>";
- }
-
- g_message ("SIGNALLING: send: Terminating call: %s", send_reason);
- }
-
- everyone = tp_intset_new_containing (tp_base_channel_get_target_handle
- (TP_BASE_CHANNEL (self)));
- tp_intset_add (everyone, self->group.self_handle);
- tp_group_mixin_change_members ((GObject *) self, "",
- NULL /* nobody added */,
- everyone /* removed */,
- NULL /* nobody locally pending */,
- NULL /* nobody remotely pending */,
- actor,
- reason);
- tp_intset_destroy (everyone);
-
- g_signal_emit (self, signals[SIGNAL_CALL_TERMINATED], 0);
- tp_base_channel_destroyed (TP_BASE_CHANNEL (self));
- }
-}
-
-static void
-dispose (GObject *object)
-{
- ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (object);
-
- if (self->priv->disposed)
- return;
-
- self->priv->disposed = TRUE;
-
- g_hash_table_unref (self->priv->streams);
- self->priv->streams = NULL;
-
- example_callable_media_channel_close (self, self->group.self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- ((GObjectClass *) example_callable_media_channel_parent_class)->dispose (object);
-}
-
-static void
-finalize (GObject *object)
-{
- 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)
-{
- ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (object);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
- (tp_base_channel_get_connection (TP_BASE_CHANNEL (self)),
- TP_HANDLE_TYPE_CONTACT);
-
- /* In connection managers that supported the RequestChannel method for
- * streamed media channels, it would be necessary to support adding the
- * called contact to the members of an outgoing call. However, in this
- * legacy-free example, we don't support that usage, so the only use for
- * AddMembers is to accept an incoming call.
- */
-
- if (member == self->group.self_handle &&
- tp_handle_set_is_member (self->group.local_pending, member))
- {
- /* We're in local-pending, move to members to accept. */
- TpIntset *set = tp_intset_new_containing (member);
- GHashTableIter iter;
- gpointer v;
-
- g_assert (self->priv->progress == PROGRESS_CALLING);
-
- g_message ("SIGNALLING: send: Accepting incoming call from %s",
- tp_handle_inspect (contact_repo, tp_base_channel_get_target_handle
- (TP_BASE_CHANNEL (self))));
-
- self->priv->progress = PROGRESS_ACTIVE;
-
- tp_group_mixin_change_members (object, "",
- set /* added */,
- NULL /* nobody removed */,
- NULL /* nobody added to local pending */,
- NULL /* nobody added to remote pending */,
- member /* actor */, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- tp_intset_destroy (set);
-
- g_hash_table_iter_init (&iter, self->priv->streams);
-
- while (g_hash_table_iter_next (&iter, NULL, &v))
- {
- /* we accept the proposed stream direction... */
- example_callable_media_stream_accept_proposed_direction (v);
- /* ... and the stream tries to connect */
- example_callable_media_stream_connect (v);
- }
-
- return TRUE;
- }
-
- /* Otherwise it's a meaningless request, so reject it. */
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Cannot add handle %u to channel", member);
- return FALSE;
-}
-
-static gboolean
-remove_member_with_reason (GObject *object,
- TpHandle member,
- const gchar *message,
- guint reason,
- GError **error)
-{
- ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (object);
-
- /* The TpGroupMixin won't call this unless removing the member is allowed
- * by the group flags, which in this case means it must be our own handle
- * (because the other user never appears in local-pending).
- */
-
- g_assert (member == self->group.self_handle);
-
- example_callable_media_channel_close (self, self->group.self_handle, reason);
- return TRUE;
-}
-
-static void
-channel_close (TpBaseChannel *channel)
-{
- ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (channel);
-
- example_callable_media_channel_close (self, self->group.self_handle,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-}
-
-static void
-example_callable_media_channel_class_init (ExampleCallableMediaChannelClass *klass)
-{
- GObjectClass *object_class = (GObjectClass *) klass;
- GParamSpec *param_spec;
- TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass);
-
- 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;
-
- base_class->channel_type = TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA;
- base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT;
- base_class->interfaces = example_callable_media_channel_interfaces;
-
- base_class->close = channel_close;
-
- param_spec = g_param_spec_uint ("simulation-delay", "Simulation delay",
- "Delay between simulated network events",
- 0, G_MAXUINT32, 1000,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_SIMULATION_DELAY,
- param_spec);
-
- param_spec = g_param_spec_boolean ("initial-audio", "Initial audio?",
- "True if this channel had an audio stream when first announced",
- FALSE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIAL_AUDIO,
- param_spec);
-
- param_spec = g_param_spec_boolean ("initial-video", "Initial video?",
- "True if this channel had a video stream when first announced",
- FALSE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIAL_VIDEO,
- param_spec);
-
- signals[SIGNAL_CALL_TERMINATED] = g_signal_new ("call-terminated",
- G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- tp_group_mixin_class_init (object_class,
- G_STRUCT_OFFSET (ExampleCallableMediaChannelClass, group_class),
- add_member,
- NULL);
- tp_group_mixin_class_allow_self_removal (object_class);
- 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
-media_list_streams (TpSvcChannelTypeStreamedMedia *iface,
- DBusGMethodInvocation *context)
-{
- ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
- GPtrArray *array = g_ptr_array_sized_new (g_hash_table_size (
- self->priv->streams));
- GHashTableIter iter;
- gpointer v;
-
- g_hash_table_iter_init (&iter, self->priv->streams);
-
- while (g_hash_table_iter_next (&iter, NULL, &v))
- {
- ExampleCallableMediaStream *stream = v;
- GValueArray *va;
-
- g_object_get (stream,
- "stream-info", &va,
- NULL);
-
- g_ptr_array_add (array, va);
- }
-
- tp_svc_channel_type_streamed_media_return_from_list_streams (context,
- array);
- g_ptr_array_foreach (array, (GFunc) g_value_array_free, NULL);
- g_ptr_array_unref (array);
-}
-
-static void
-media_remove_streams (TpSvcChannelTypeStreamedMedia *iface,
- const GArray *stream_ids,
- DBusGMethodInvocation *context)
-{
- ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
- guint i;
-
- for (i = 0; i < stream_ids->len; i++)
- {
- guint id = g_array_index (stream_ids, guint, i);
-
- if (g_hash_table_lookup (self->priv->streams,
- GUINT_TO_POINTER (id)) == NULL)
- {
- GError *error = g_error_new (TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "No stream with ID %u in this channel", id);
-
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
- }
-
- for (i = 0; i < stream_ids->len; i++)
- {
- guint id = g_array_index (stream_ids, guint, i);
-
- example_callable_media_stream_close (
- g_hash_table_lookup (self->priv->streams, GUINT_TO_POINTER (id)));
- }
-
- 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);
- ExampleCallableMediaStream *stream = g_hash_table_lookup (
- self->priv->streams, GUINT_TO_POINTER (stream_id));
- GError *error = NULL;
-
- if (stream == NULL)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "No stream with ID %u in this channel", stream_id);
- goto error;
- }
-
- if (stream_direction > TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Stream direction %u is not valid", stream_direction);
- goto error;
- }
-
- /* In some protocols, streams cannot be neither sending nor receiving, so
- * if a stream is set to TP_MEDIA_STREAM_DIRECTION_NONE, this is equivalent
- * to removing it with RemoveStreams. (This is true in XMPP, for instance.)
- *
- * If this was the case, there would be code like this here:
- *
- * if (stream_direction == TP_MEDIA_STREAM_DIRECTION_NONE)
- * {
- * example_callable_media_stream_close (stream);
- * tp_svc_channel_type_streamed_media_return_from_request_stream_direction (
- * context);
- * return;
- * }
- *
- * However, for this example we'll emulate a protocol where streams can be
- * directionless.
- */
-
- if (!example_callable_media_stream_change_direction (stream,
- stream_direction, &error))
- goto error;
-
- tp_svc_channel_type_streamed_media_return_from_request_stream_direction (
- context);
- return;
-
-error:
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-}
-
-static void
-stream_removed_cb (ExampleCallableMediaStream *stream,
- ExampleCallableMediaChannel *self)
-{
- guint id;
-
- g_object_get (stream,
- "id", &id,
- NULL);
-
- g_signal_handlers_disconnect_matched (stream, G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, self);
- g_hash_table_remove (self->priv->streams, GUINT_TO_POINTER (id));
- tp_svc_channel_type_streamed_media_emit_stream_removed (self, id);
-
- if (g_hash_table_size (self->priv->streams) == 0)
- {
- /* no streams left, so the call terminates */
- example_callable_media_channel_close (self, 0,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- }
-}
-
-static void
-stream_direction_changed_cb (ExampleCallableMediaStream *stream,
- ExampleCallableMediaChannel *self)
-{
- guint id, direction, pending;
-
- g_object_get (stream,
- "id", &id,
- "direction", &direction,
- "pending-send", &pending,
- NULL);
-
- tp_svc_channel_type_streamed_media_emit_stream_direction_changed (self, id,
- direction, pending);
-}
-
-static void
-stream_state_changed_cb (ExampleCallableMediaStream *stream,
- GParamSpec *spec G_GNUC_UNUSED,
- ExampleCallableMediaChannel *self)
-{
- guint id, state;
-
- g_object_get (stream,
- "id", &id,
- "state", &state,
- NULL);
-
- tp_svc_channel_type_streamed_media_emit_stream_state_changed (self, id,
- state);
-}
-
-static gboolean
-simulate_contact_ended_cb (gpointer p)
-{
- ExampleCallableMediaChannel *self = p;
-
- /* if the call has been cancelled while we were waiting for the
- * contact to do so, do nothing! */
- if (self->priv->progress == PROGRESS_ENDED)
- return FALSE;
-
- g_message ("SIGNALLING: receive: call terminated: <call-terminated/>");
-
- example_callable_media_channel_close (self,
- tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self)),
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- return FALSE;
-}
-
-static gboolean
-simulate_contact_answered_cb (gpointer p)
-{
- ExampleCallableMediaChannel *self = p;
- TpIntset *peer_set;
- GHashTableIter iter;
- gpointer v;
- TpHandleRepoIface *contact_repo;
- const gchar *peer;
- TpHandle target;
-
- /* if the call has been cancelled while we were waiting for the
- * contact to answer, do nothing */
- if (self->priv->progress == PROGRESS_ENDED)
- return FALSE;
-
- /* otherwise, we're waiting for a response from the contact, which now
- * arrives */
- g_assert (self->priv->progress == PROGRESS_CALLING);
-
- g_message ("SIGNALLING: receive: contact answered our call");
-
- self->priv->progress = PROGRESS_ACTIVE;
-
- target = tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self));
- peer_set = tp_intset_new_containing (target);
- tp_group_mixin_change_members ((GObject *) self, "",
- peer_set /* added */,
- NULL /* nobody removed */,
- NULL /* nobody added to local-pending */,
- NULL /* nobody added to remote-pending */,
- target /* actor */,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (peer_set);
-
- g_hash_table_iter_init (&iter, self->priv->streams);
-
- while (g_hash_table_iter_next (&iter, NULL, &v))
- {
- /* remote contact accepts our proposed stream direction... */
- example_callable_media_stream_simulate_contact_agreed_to_send (v);
- /* ... and the stream tries to connect */
- example_callable_media_stream_connect (v);
- }
-
- contact_repo = tp_base_connection_get_handles
- (tp_base_channel_get_connection (TP_BASE_CHANNEL (self)),
- TP_HANDLE_TYPE_CONTACT);
- peer = tp_handle_inspect (contact_repo, target);
-
- /* If the contact's ID contains the magic string "(terminate)", simulate
- * them hanging up after a moment. */
- if (strstr (peer, "(terminate)") != NULL)
- {
- g_timeout_add_full (G_PRIORITY_DEFAULT,
- self->priv->simulation_delay,
- simulate_contact_ended_cb, g_object_ref (self),
- g_object_unref);
- }
-
- return FALSE;
-}
-
-static gboolean
-simulate_contact_busy_cb (gpointer p)
-{
- ExampleCallableMediaChannel *self = p;
-
- /* if the call has been cancelled while we were waiting for the
- * contact to answer, do nothing */
- if (self->priv->progress == PROGRESS_ENDED)
- return FALSE;
-
- /* otherwise, we're waiting for a response from the contact, which now
- * arrives */
- g_assert (self->priv->progress == PROGRESS_CALLING);
-
- g_message ("SIGNALLING: receive: call terminated: <user-is-busy/>");
-
- example_callable_media_channel_close (self,
- tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self)),
- TP_CHANNEL_GROUP_CHANGE_REASON_BUSY);
-
- return FALSE;
-}
-
-static ExampleCallableMediaStream *
-example_callable_media_channel_add_stream (ExampleCallableMediaChannel *self,
- TpMediaStreamType media_type,
- gboolean locally_requested)
-{
- ExampleCallableMediaStream *stream;
- guint id = self->priv->next_stream_id++;
- guint state, direction, pending_send;
- TpHandle target;
-
- if (locally_requested)
- {
- g_message ("SIGNALLING: send: new %s stream",
- media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video");
- }
-
- target = tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self));
- stream = g_object_new (EXAMPLE_TYPE_CALLABLE_MEDIA_STREAM,
- "channel", self,
- "id", id,
- "handle", target,
- "type", media_type,
- "locally-requested", locally_requested,
- NULL);
-
- g_hash_table_insert (self->priv->streams, GUINT_TO_POINTER (id), stream);
-
- tp_svc_channel_type_streamed_media_emit_stream_added (self, id,
- target, media_type);
-
- g_object_get (stream,
- "state", &state,
- "direction", &direction,
- "pending-send", &pending_send,
- NULL);
-
- /* this is the "implicit" initial state mandated by telepathy-spec */
- if (state != TP_MEDIA_STREAM_STATE_DISCONNECTED)
- {
- tp_svc_channel_type_streamed_media_emit_stream_state_changed (self, id,
- state);
- }
-
- /* this is the "implicit" initial direction mandated by telepathy-spec */
- if (direction != TP_MEDIA_STREAM_DIRECTION_RECEIVE ||
- pending_send != TP_MEDIA_STREAM_PENDING_LOCAL_SEND)
- {
- tp_svc_channel_type_streamed_media_emit_stream_direction_changed (self,
- id, direction, pending_send);
- }
-
- g_signal_connect (stream, "removed", G_CALLBACK (stream_removed_cb),
- self);
- g_signal_connect (stream, "notify::state",
- G_CALLBACK (stream_state_changed_cb), self);
- g_signal_connect (stream, "direction-changed",
- G_CALLBACK (stream_direction_changed_cb), self);
-
- if (self->priv->progress == PROGRESS_ACTIVE)
- {
- example_callable_media_stream_connect (stream);
- }
-
- return stream;
-}
-
-static void
-media_request_streams (TpSvcChannelTypeStreamedMedia *iface,
- guint contact_handle,
- const GArray *media_types,
- DBusGMethodInvocation *context)
-{
- ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
- (tp_base_channel_get_connection (TP_BASE_CHANNEL (self)),
- TP_HANDLE_TYPE_CONTACT);
- GPtrArray *array;
- guint i;
- GError *error = NULL;
- TpHandle target;
-
- if (!tp_handle_is_valid (contact_repo, contact_handle, &error))
- goto error;
-
- target = tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self));
- if (contact_handle != target)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "This channel is for handle #%u, we can't make a stream to #%u",
- target, contact_handle);
- goto error;
- }
-
- if (self->priv->progress == PROGRESS_ENDED)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Call has terminated");
- goto error;
- }
-
- for (i = 0; i < media_types->len; i++)
- {
- guint media_type = g_array_index (media_types, guint, i);
-
- switch (media_type)
- {
- case TP_MEDIA_STREAM_TYPE_AUDIO:
- case TP_MEDIA_STREAM_TYPE_VIDEO:
- break;
- default:
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "%u is not a valid Media_Stream_Type", media_type);
- goto error;
- }
- }
-
- array = g_ptr_array_sized_new (media_types->len);
-
- for (i = 0; i < media_types->len; i++)
- {
- guint media_type = g_array_index (media_types, guint, i);
- ExampleCallableMediaStream *stream;
- GValueArray *info;
-
- if (self->priv->progress < PROGRESS_CALLING)
- {
- TpIntset *peer_set = tp_intset_new_containing (target);
- const gchar *peer;
-
- g_message ("SIGNALLING: send: new streamed media call");
- self->priv->progress = PROGRESS_CALLING;
-
- tp_group_mixin_change_members ((GObject *) self, "",
- NULL /* nobody added */,
- NULL /* nobody removed */,
- NULL /* nobody added to local-pending */,
- peer_set /* added to remote-pending */,
- self->group.self_handle /* actor */,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- tp_intset_destroy (peer_set);
-
- /* In this example there is no real contact, so just simulate them
- * answering after a short time - unless the contact's name
- * contains "(no answer)" or "(busy)" */
-
- peer = tp_handle_inspect (contact_repo, target);
-
- if (strstr (peer, "(busy)") != NULL)
- {
- g_timeout_add_full (G_PRIORITY_DEFAULT,
- self->priv->simulation_delay,
- simulate_contact_busy_cb, g_object_ref (self),
- g_object_unref);
- }
- else if (strstr (peer, "(no answer)") != NULL)
- {
- /* do nothing - the call just rings forever */
- }
- else
- {
- g_timeout_add_full (G_PRIORITY_DEFAULT,
- self->priv->simulation_delay,
- simulate_contact_answered_cb, g_object_ref (self),
- g_object_unref);
- }
- }
-
- stream = example_callable_media_channel_add_stream (self, media_type,
- TRUE);
-
- g_object_get (stream,
- "stream-info", &info,
- NULL);
-
- g_ptr_array_add (array, info);
- }
-
- tp_svc_channel_type_streamed_media_return_from_request_streams (context,
- array);
- g_boxed_free (TP_ARRAY_TYPE_MEDIA_STREAM_INFO_LIST, array);
-
- return;
-
-error:
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-}
-
-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
-}
-
-static gboolean
-simulate_hold (gpointer p)
-{
- ExampleCallableMediaChannel *self = p;
-
- self->priv->hold_state = TP_LOCAL_HOLD_STATE_HELD;
- g_message ("SIGNALLING: hold state changed to held");
- tp_svc_channel_interface_hold_emit_hold_state_changed (self,
- self->priv->hold_state, self->priv->hold_state_reason);
- return FALSE;
-}
-
-static gboolean
-simulate_unhold (gpointer p)
-{
- ExampleCallableMediaChannel *self = p;
-
- self->priv->hold_state = TP_LOCAL_HOLD_STATE_UNHELD;
- g_message ("SIGNALLING: hold state changed to unheld");
- tp_svc_channel_interface_hold_emit_hold_state_changed (self,
- self->priv->hold_state, self->priv->hold_state_reason);
- return FALSE;
-}
-
-static gboolean
-simulate_inability_to_unhold (gpointer p)
-{
- ExampleCallableMediaChannel *self = p;
-
- self->priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD;
- g_message ("SIGNALLING: unable to unhold - hold state changed to "
- "pending hold");
- tp_svc_channel_interface_hold_emit_hold_state_changed (self,
- self->priv->hold_state, self->priv->hold_state_reason);
- /* hold again */
- g_timeout_add_full (G_PRIORITY_DEFAULT,
- self->priv->simulation_delay,
- simulate_hold, g_object_ref (self),
- g_object_unref);
- return FALSE;
-}
-
-static void
-hold_get_hold_state (TpSvcChannelInterfaceHold *iface,
- DBusGMethodInvocation *context)
-{
- ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
-
- tp_svc_channel_interface_hold_return_from_get_hold_state (context,
- self->priv->hold_state, self->priv->hold_state_reason);
-}
-
-static void
-hold_request_hold (TpSvcChannelInterfaceHold *iface,
- gboolean hold,
- DBusGMethodInvocation *context)
-{
- ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
- (tp_base_channel_get_connection (TP_BASE_CHANNEL (self)),
- TP_HANDLE_TYPE_CONTACT);
- GError *error = NULL;
- const gchar *peer;
- GSourceFunc callback;
- TpHandle target;
-
- if ((hold && self->priv->hold_state == TP_LOCAL_HOLD_STATE_HELD) ||
- (!hold && self->priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD))
- {
- tp_svc_channel_interface_hold_return_from_request_hold (context);
- return;
- }
-
- target = tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self));
- peer = tp_handle_inspect (contact_repo, target);
-
- if (!hold && strstr (peer, "(no unhold)") != NULL)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "unable to unhold");
- goto error;
- }
-
- self->priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_REQUESTED;
-
- if (hold)
- {
- self->priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD;
- callback = simulate_hold;
- }
- else
- {
- self->priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_UNHOLD;
-
- peer = tp_handle_inspect (contact_repo, target);
-
- if (strstr (peer, "(inability to unhold)") != NULL)
- {
- callback = simulate_inability_to_unhold;
- }
- else
- {
- callback = simulate_unhold;
- }
- }
-
- g_message ("SIGNALLING: hold state changed to pending %s",
- (hold ? "hold" : "unhold"));
- tp_svc_channel_interface_hold_emit_hold_state_changed (iface,
- self->priv->hold_state, self->priv->hold_state_reason);
-
- g_timeout_add_full (G_PRIORITY_DEFAULT,
- self->priv->simulation_delay,
- callback, g_object_ref (self),
- g_object_unref);
-
- tp_svc_channel_interface_hold_return_from_request_hold (context);
- return;
-
-error:
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-}
-
-
-void
-hold_iface_init (gpointer iface,
- gpointer data)
-{
- TpSvcChannelInterfaceHoldClass *klass = iface;
-
-#define IMPLEMENT(x) \
- tp_svc_channel_interface_hold_implement_##x (klass, hold_##x)
- IMPLEMENT (get_hold_state);
- IMPLEMENT (request_hold);
-#undef IMPLEMENT
-}
-
-static void
-dtmf_start_tone (TpSvcChannelInterfaceDTMF *iface,
- guint stream_id,
- guchar event,
- DBusGMethodInvocation *context)
-{
- ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
- ExampleCallableMediaStream *stream = g_hash_table_lookup (self->priv->streams,
- GUINT_TO_POINTER (stream_id));
- GError *error = NULL;
- guint media_type;
-
- if (stream == NULL)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "No stream with ID %u in this channel", stream_id);
- goto error;
- }
-
- g_object_get (G_OBJECT (stream), "type", &media_type, NULL);
- if (media_type != TP_MEDIA_STREAM_TYPE_AUDIO)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "DTMF is only supported by audio streams");
- goto error;
- }
-
- tp_svc_channel_interface_dtmf_return_from_start_tone (context);
-
- return;
-
-error:
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-}
-
-static void
-dtmf_stop_tone (TpSvcChannelInterfaceDTMF *iface,
- guint stream_id,
- DBusGMethodInvocation *context)
-{
- ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
- ExampleCallableMediaStream *stream = g_hash_table_lookup (self->priv->streams,
- GUINT_TO_POINTER (stream_id));
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
- (tp_base_channel_get_connection (TP_BASE_CHANNEL (self)),
- TP_HANDLE_TYPE_CONTACT);
- GError *error = NULL;
- const gchar *peer;
- guint media_type;
-
- if (stream == NULL)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "No stream with ID %u in this channel", stream_id);
- goto error;
- }
-
- g_object_get (G_OBJECT (stream), "type", &media_type, NULL);
- if (media_type != TP_MEDIA_STREAM_TYPE_AUDIO)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "DTMF is only supported by audio streams");
- goto error;
- }
-
- peer = tp_handle_inspect (contact_repo,
- tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self)));
- if (strstr (peer, "(no continuous tone)") != NULL)
- {
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Continuous tones are not supported by this stream");
- goto error;
- }
-
- tp_svc_channel_interface_dtmf_return_from_stop_tone (context);
-
- return;
-
-error:
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-}
-
-static void
-dtmf_iface_init (gpointer iface,
- gpointer data)
-{
- TpSvcChannelInterfaceDTMFClass *klass = iface;
-
-#define IMPLEMENT(x) \
- tp_svc_channel_interface_dtmf_implement_##x (klass, dtmf_##x)
- IMPLEMENT (start_tone);
- IMPLEMENT (stop_tone);
-#undef IMPLEMENT
-}
diff --git a/examples/cm/callable/media-channel.h b/examples/cm/callable/media-channel.h
deleted file mode 100644
index e45f6cd19..000000000
--- a/examples/cm/callable/media-channel.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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 <telepathy-glib/base-channel.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 {
- TpBaseChannelClass parent_class;
- TpGroupMixinClass group_class;
-
- ExampleCallableMediaChannelClassPrivate *priv;
-};
-
-struct _ExampleCallableMediaChannel {
- TpBaseChannel parent;
- TpGroupMixin group;
-
- ExampleCallableMediaChannelPrivate *priv;
-};
-
-G_END_DECLS
-
-#endif
diff --git a/examples/cm/callable/media-manager.h b/examples/cm/callable/media-manager.h
deleted file mode 100644
index 5be239e6e..000000000
--- a/examples/cm/callable/media-manager.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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
diff --git a/examples/cm/callable/media-stream.c b/examples/cm/callable/media-stream.c
deleted file mode 100644
index 22da0bc87..000000000
--- a/examples/cm/callable/media-stream.c
+++ /dev/null
@@ -1,652 +0,0 @@
-/*
- * media-stream.c - a stream in a streamed media call.
- *
- * In connection managers with MediaSignalling, this object would be a D-Bus
- * object in its own right. In this CM, MediaSignalling is not used, and this
- * object just represents internal state of the MediaChannel.
- *
- * 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 "media-stream.h"
-
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/gtypes.h>
-
-#include "media-channel.h"
-
-G_DEFINE_TYPE (ExampleCallableMediaStream,
- example_callable_media_stream,
- G_TYPE_OBJECT)
-
-enum
-{
- PROP_CHANNEL = 1,
- PROP_ID,
- PROP_HANDLE,
- PROP_TYPE,
- PROP_STATE,
- PROP_PENDING_SEND,
- PROP_DIRECTION,
- PROP_STREAM_INFO,
- PROP_SIMULATION_DELAY,
- PROP_LOCALLY_REQUESTED,
- N_PROPS
-};
-
-enum
-{
- SIGNAL_REMOVED,
- SIGNAL_DIRECTION_CHANGED,
- N_SIGNALS
-};
-
-static guint signals[N_SIGNALS] = { 0 };
-
-struct _ExampleCallableMediaStreamPrivate
-{
- TpBaseConnection *conn;
- ExampleCallableMediaChannel *channel;
- guint id;
- TpHandle handle;
- TpMediaStreamType type;
- TpMediaStreamState state;
- TpMediaStreamDirection direction;
- TpMediaStreamPendingSend pending_send;
-
- guint simulation_delay;
-
- gulong call_terminated_id;
-
- guint connected_event_id;
-
- gboolean locally_requested;
- gboolean removed;
-};
-
-static void
-example_callable_media_stream_init (ExampleCallableMediaStream *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- EXAMPLE_TYPE_CALLABLE_MEDIA_STREAM,
- ExampleCallableMediaStreamPrivate);
-
- /* start off directionless */
- self->priv->direction = TP_MEDIA_STREAM_DIRECTION_NONE;
- self->priv->pending_send = 0;
- self->priv->state = TP_MEDIA_STREAM_STATE_DISCONNECTED;
-}
-
-static void
-call_terminated_cb (ExampleCallableMediaChannel *channel,
- ExampleCallableMediaStream *self)
-{
- g_signal_handler_disconnect (channel, self->priv->call_terminated_id);
- self->priv->call_terminated_id = 0;
- example_callable_media_stream_close (self);
-}
-
-static void
-constructed (GObject *object)
-{
- ExampleCallableMediaStream *self = EXAMPLE_CALLABLE_MEDIA_STREAM (object);
- void (*chain_up) (GObject *) =
- ((GObjectClass *) example_callable_media_stream_parent_class)->constructed;
-
- if (chain_up != NULL)
- chain_up (object);
-
- g_object_get (self->priv->channel,
- "connection", &self->priv->conn,
- NULL);
- self->priv->call_terminated_id = g_signal_connect (self->priv->channel,
- "call-terminated", G_CALLBACK (call_terminated_cb), self);
-
- if (self->priv->handle != 0)
- {
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- self->priv->conn, TP_HANDLE_TYPE_CONTACT);
-
- tp_handle_ref (contact_repo, self->priv->handle);
- }
-}
-
-static void
-get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- ExampleCallableMediaStream *self = EXAMPLE_CALLABLE_MEDIA_STREAM (object);
-
- switch (property_id)
- {
- case PROP_ID:
- g_value_set_uint (value, self->priv->id);
- break;
-
- case PROP_HANDLE:
- g_value_set_uint (value, self->priv->handle);
- break;
-
- case PROP_TYPE:
- g_value_set_uint (value, self->priv->type);
- break;
-
- case PROP_STATE:
- g_value_set_uint (value, self->priv->state);
- break;
-
- case PROP_PENDING_SEND:
- g_value_set_uint (value, self->priv->pending_send);
- break;
-
- case PROP_DIRECTION:
- g_value_set_uint (value, self->priv->direction);
- break;
-
- case PROP_CHANNEL:
- g_value_set_object (value, self->priv->channel);
- break;
-
- case PROP_STREAM_INFO:
- {
- GValueArray *va = g_value_array_new (6);
- guint i;
-
- for (i = 0; i < 6; i++)
- {
- g_value_array_append (va, NULL);
- g_value_init (va->values + i, G_TYPE_UINT);
- }
-
- g_value_set_uint (va->values + 0, self->priv->id);
- g_value_set_uint (va->values + 1, self->priv->handle);
- g_value_set_uint (va->values + 2, self->priv->type);
- g_value_set_uint (va->values + 3, self->priv->state);
- g_value_set_uint (va->values + 4, self->priv->direction);
- g_value_set_uint (va->values + 5, self->priv->pending_send);
-
- g_value_take_boxed (value, va);
- }
- break;
-
- case PROP_SIMULATION_DELAY:
- g_value_set_uint (value, self->priv->simulation_delay);
- break;
-
- case PROP_LOCALLY_REQUESTED:
- g_value_set_boolean (value, self->priv->locally_requested);
- 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)
-{
- ExampleCallableMediaStream *self = EXAMPLE_CALLABLE_MEDIA_STREAM (object);
-
- switch (property_id)
- {
- case PROP_ID:
- self->priv->id = g_value_get_uint (value);
- break;
-
- case PROP_HANDLE:
- self->priv->handle = g_value_get_uint (value);
- break;
-
- case PROP_TYPE:
- self->priv->type = g_value_get_uint (value);
- break;
-
- case PROP_CHANNEL:
- g_assert (self->priv->channel == NULL);
- self->priv->channel = g_value_dup_object (value);
- break;
-
- case PROP_SIMULATION_DELAY:
- self->priv->simulation_delay = g_value_get_uint (value);
- break;
-
- case PROP_LOCALLY_REQUESTED:
- self->priv->locally_requested = g_value_get_boolean (value);
-
- if (self->priv->locally_requested)
- {
- example_callable_media_stream_change_direction (self,
- TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, NULL);
- }
- else
- {
- example_callable_media_stream_receive_direction_request (self,
- TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL);
- }
-
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-dispose (GObject *object)
-{
- ExampleCallableMediaStream *self = EXAMPLE_CALLABLE_MEDIA_STREAM (object);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- self->priv->conn, TP_HANDLE_TYPE_CONTACT);
-
- example_callable_media_stream_close (self);
-
- if (self->priv->handle != 0)
- {
- tp_handle_unref (contact_repo, self->priv->handle);
- self->priv->handle = 0;
- }
-
- if (self->priv->channel != NULL)
- {
- if (self->priv->call_terminated_id != 0)
- {
- g_signal_handler_disconnect (self->priv->channel,
- self->priv->call_terminated_id);
- self->priv->call_terminated_id = 0;
- }
-
- g_object_unref (self->priv->channel);
- self->priv->channel = NULL;
- }
-
- if (self->priv->conn != NULL)
- {
- g_object_unref (self->priv->conn);
- self->priv->conn = NULL;
- }
-
- ((GObjectClass *) example_callable_media_stream_parent_class)->dispose (object);
-}
-
-static void
-example_callable_media_stream_class_init (ExampleCallableMediaStreamClass *klass)
-{
- GObjectClass *object_class = (GObjectClass *) klass;
- GParamSpec *param_spec;
-
- g_type_class_add_private (klass,
- sizeof (ExampleCallableMediaStreamPrivate));
-
- object_class->constructed = constructed;
- object_class->set_property = set_property;
- object_class->get_property = get_property;
- object_class->dispose = dispose;
-
- param_spec = g_param_spec_object ("channel", "ExampleCallableMediaChannel",
- "Media channel that owns this stream",
- EXAMPLE_TYPE_CALLABLE_MEDIA_CHANNEL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CHANNEL, param_spec);
-
- param_spec = g_param_spec_uint ("id", "Stream ID",
- "ID of this stream",
- 0, G_MAXUINT32, 0,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_ID, param_spec);
-
- param_spec = g_param_spec_uint ("handle", "Peer's TpHandle",
- "The handle with which this stream communicates or 0 if not applicable",
- 0, G_MAXUINT32, 0,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_HANDLE, param_spec);
-
- param_spec = g_param_spec_uint ("type", "TpMediaStreamType",
- "Media stream type",
- 0, NUM_TP_MEDIA_STREAM_TYPES - 1, 0,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_TYPE, param_spec);
-
- param_spec = g_param_spec_uint ("state", "TpMediaStreamState",
- "Media stream connection state",
- 0, NUM_TP_MEDIA_STREAM_STATES - 1, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_STATE, param_spec);
-
- param_spec = g_param_spec_uint ("direction", "TpMediaStreamDirection",
- "Media stream direction",
- 0, NUM_TP_MEDIA_STREAM_DIRECTIONS - 1, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_DIRECTION, param_spec);
-
- param_spec = g_param_spec_uint ("pending-send", "TpMediaStreamPendingSend",
- "Requested media stream directions pending approval",
- 0,
- TP_MEDIA_STREAM_PENDING_LOCAL_SEND | TP_MEDIA_STREAM_PENDING_REMOTE_SEND,
- 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_PENDING_SEND, param_spec);
-
- param_spec = g_param_spec_boxed ("stream-info", "Stream info",
- "6-entry GValueArray as returned by ListStreams and RequestStreams",
- TP_STRUCT_TYPE_MEDIA_STREAM_INFO,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_STREAM_INFO, param_spec);
-
- param_spec = g_param_spec_uint ("simulation-delay", "Simulation delay",
- "Delay between simulated network events",
- 0, G_MAXUINT32, 1000,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_SIMULATION_DELAY,
- param_spec);
-
- param_spec = g_param_spec_boolean ("locally-requested", "Locally requested?",
- "True if this channel was requested by the local user",
- FALSE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_LOCALLY_REQUESTED,
- param_spec);
-
- signals[SIGNAL_REMOVED] = g_signal_new ("removed",
- G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- signals[SIGNAL_DIRECTION_CHANGED] = g_signal_new ("direction-changed",
- G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-void
-example_callable_media_stream_close (ExampleCallableMediaStream *self)
-{
- if (!self->priv->removed)
- {
- self->priv->removed = TRUE;
-
- g_message ("Sending to server: Closing stream %u",
- self->priv->id);
-
- if (self->priv->connected_event_id != 0)
- {
- g_source_remove (self->priv->connected_event_id);
- }
-
- /* this has to come last, because the MediaChannel may unref us in
- * response to the removed signal */
- g_signal_emit (self, signals[SIGNAL_REMOVED], 0);
- }
-}
-
-void
-example_callable_media_stream_accept_proposed_direction (
- ExampleCallableMediaStream *self)
-{
- if (self->priv->removed ||
- !(self->priv->pending_send & TP_MEDIA_STREAM_PENDING_LOCAL_SEND))
- return;
-
- g_message ("SIGNALLING: send: OK, I'll send you media on stream %u",
- self->priv->id);
-
- self->priv->direction |= TP_MEDIA_STREAM_DIRECTION_SEND;
- self->priv->pending_send &= ~TP_MEDIA_STREAM_PENDING_LOCAL_SEND;
-
- g_signal_emit (self, signals[SIGNAL_DIRECTION_CHANGED], 0);
-}
-
-void
-example_callable_media_stream_simulate_contact_agreed_to_send (
- ExampleCallableMediaStream *self)
-{
- if (self->priv->removed ||
- !(self->priv->pending_send & TP_MEDIA_STREAM_PENDING_REMOTE_SEND))
- return;
-
- g_message ("SIGNALLING: receive: OK, I'll send you media on stream %u",
- self->priv->id);
-
- self->priv->direction |= TP_MEDIA_STREAM_DIRECTION_RECEIVE;
- self->priv->pending_send &= ~TP_MEDIA_STREAM_PENDING_REMOTE_SEND;
-
- g_signal_emit (self, signals[SIGNAL_DIRECTION_CHANGED], 0);
-}
-
-static gboolean
-simulate_contact_agreed_to_send_cb (gpointer p)
-{
- example_callable_media_stream_simulate_contact_agreed_to_send (p);
- return FALSE;
-}
-
-gboolean
-example_callable_media_stream_change_direction (
- ExampleCallableMediaStream *self,
- TpMediaStreamDirection direction,
- GError **error)
-{
- gboolean sending =
- ((self->priv->direction & TP_MEDIA_STREAM_DIRECTION_SEND) != 0);
- gboolean receiving =
- ((self->priv->direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE) != 0);
- gboolean want_to_send =
- ((direction & TP_MEDIA_STREAM_DIRECTION_SEND) != 0);
- gboolean want_to_receive =
- ((direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE) != 0);
- gboolean pending_remote_send =
- ((self->priv->pending_send & TP_MEDIA_STREAM_PENDING_REMOTE_SEND) != 0);
- gboolean pending_local_send =
- ((self->priv->pending_send & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) != 0);
- gboolean changed = FALSE;
-
- if (want_to_send)
- {
- if (!sending)
- {
- if (pending_local_send)
- {
- g_message ("SIGNALLING: send: I will now send you media on "
- "stream %u", self->priv->id);
- }
-
- g_message ("MEDIA: Sending media to peer for stream %u",
- self->priv->id);
- changed = TRUE;
- self->priv->direction |= TP_MEDIA_STREAM_DIRECTION_SEND;
- }
- }
- else
- {
- if (sending)
- {
- g_message ("SIGNALLING: send: I will no longer send you media on "
- "stream %u", self->priv->id);
- g_message ("MEDIA: No longer sending media to peer for stream %u",
- self->priv->id);
- changed = TRUE;
- self->priv->direction &= ~TP_MEDIA_STREAM_DIRECTION_SEND;
- }
- else if (pending_local_send)
- {
- g_message ("SIGNALLING: send: No, I refuse to send you media on "
- "stream %u", self->priv->id);
- changed = TRUE;
- self->priv->pending_send &= ~TP_MEDIA_STREAM_PENDING_LOCAL_SEND;
- }
- }
-
- if (want_to_receive)
- {
- if (!receiving && !pending_remote_send)
- {
- g_message ("SIGNALLING: send: Please start sending me stream %u",
- self->priv->id);
- changed = TRUE;
- self->priv->pending_send |= TP_MEDIA_STREAM_PENDING_REMOTE_SEND;
- g_timeout_add_full (G_PRIORITY_DEFAULT, self->priv->simulation_delay,
- simulate_contact_agreed_to_send_cb, g_object_ref (self),
- g_object_unref);
- }
- }
- else
- {
- if (receiving)
- {
- g_message ("SIGNALLING: send: Please stop sending me stream %u",
- self->priv->id);
- g_message ("MEDIA: Suppressing output of stream %u",
- self->priv->id);
- changed = TRUE;
- self->priv->direction &= ~TP_MEDIA_STREAM_DIRECTION_RECEIVE;
- }
- }
-
- if (changed)
- g_signal_emit (self, signals[SIGNAL_DIRECTION_CHANGED], 0);
-
- return TRUE;
-}
-
-static gboolean
-simulate_stream_connected_cb (gpointer p)
-{
- ExampleCallableMediaStream *self = EXAMPLE_CALLABLE_MEDIA_STREAM (p);
-
- g_message ("MEDIA: stream connected");
- self->priv->state = TP_MEDIA_STREAM_STATE_CONNECTED;
- g_object_notify ((GObject *) self, "state");
-
- return FALSE;
-}
-
-void
-example_callable_media_stream_connect (ExampleCallableMediaStream *self)
-{
- /* if already trying to connect, do nothing */
- if (self->priv->connected_event_id != 0)
- return;
-
- /* simulate it taking a short time to connect */
- self->priv->connected_event_id = g_timeout_add (self->priv->simulation_delay,
- simulate_stream_connected_cb, self);
-}
-
-void
-example_callable_media_stream_receive_direction_request (
- ExampleCallableMediaStream *self,
- TpMediaStreamDirection direction)
-{
- /* The remote user wants to change the direction of this stream to
- * @direction. Shall we let him? */
- gboolean sending =
- ((self->priv->direction & TP_MEDIA_STREAM_DIRECTION_SEND) != 0);
- gboolean receiving =
- ((self->priv->direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE) != 0);
- gboolean send_requested =
- ((direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE) != 0);
- gboolean receive_requested =
- ((direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE) != 0);
- gboolean pending_remote_send =
- ((self->priv->pending_send & TP_MEDIA_STREAM_PENDING_REMOTE_SEND) != 0);
- gboolean pending_local_send =
- ((self->priv->pending_send & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) != 0);
- gboolean changed = FALSE;
-
- if (send_requested)
- {
- g_message ("SIGNALLING: receive: Please start sending me stream %u",
- self->priv->id);
-
- if (!sending)
- {
- /* ask the user for permission */
- self->priv->pending_send |= TP_MEDIA_STREAM_PENDING_LOCAL_SEND;
- changed = TRUE;
- }
- else
- {
- /* nothing to do, we're already sending on that stream */
- }
- }
- else
- {
- g_message ("SIGNALLING: receive: Please stop sending me stream %u",
- self->priv->id);
- g_message ("SIGNALLING: send: OK, not sending stream %u",
- self->priv->id);
-
- if (sending)
- {
- g_message ("MEDIA: No longer sending media to peer for stream %u",
- self->priv->id);
- self->priv->direction &= ~TP_MEDIA_STREAM_DIRECTION_SEND;
- changed = TRUE;
- }
- else if (pending_local_send)
- {
- self->priv->pending_send &= ~TP_MEDIA_STREAM_PENDING_LOCAL_SEND;
- changed = TRUE;
- }
- else
- {
- /* nothing to do, we're not sending on that stream anyway */
- }
- }
-
- if (receive_requested)
- {
- g_message ("SIGNALLING: receive: I will now send you media on stream %u",
- self->priv->id);
-
- if (!receiving)
- {
- self->priv->pending_send &= ~TP_MEDIA_STREAM_PENDING_REMOTE_SEND;
- self->priv->direction |= TP_MEDIA_STREAM_DIRECTION_RECEIVE;
- changed = TRUE;
- }
- }
- else
- {
- if (pending_remote_send)
- {
- g_message ("SIGNALLING: receive: No, I refuse to send you media on "
- "stream %u", self->priv->id);
- self->priv->pending_send &= ~TP_MEDIA_STREAM_PENDING_REMOTE_SEND;
- changed = TRUE;
- }
- else if (receiving)
- {
- g_message ("SIGNALLING: receive: I will no longer send you media on "
- "stream %u", self->priv->id);
- self->priv->direction &= ~TP_MEDIA_STREAM_DIRECTION_RECEIVE;
- changed = TRUE;
- }
- }
-
- if (changed)
- g_signal_emit (self, signals[SIGNAL_DIRECTION_CHANGED], 0);
-}
diff --git a/examples/cm/callable/media-stream.h b/examples/cm/callable/media-stream.h
deleted file mode 100644
index e7ec04804..000000000
--- a/examples/cm/callable/media-stream.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * media-stream.h - header for an example stream
- *
- * 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_STREAM_H__
-#define __EXAMPLE_CALLABLE_MEDIA_STREAM_H__
-
-#include <glib-object.h>
-
-#include <telepathy-glib/enums.h>
-
-G_BEGIN_DECLS
-
-typedef struct _ExampleCallableMediaStream ExampleCallableMediaStream;
-typedef struct _ExampleCallableMediaStreamPrivate
- ExampleCallableMediaStreamPrivate;
-
-typedef struct _ExampleCallableMediaStreamClass
- ExampleCallableMediaStreamClass;
-typedef struct _ExampleCallableMediaStreamClassPrivate
- ExampleCallableMediaStreamClassPrivate;
-
-GType example_callable_media_stream_get_type (void);
-
-#define EXAMPLE_TYPE_CALLABLE_MEDIA_STREAM \
- (example_callable_media_stream_get_type ())
-#define EXAMPLE_CALLABLE_MEDIA_STREAM(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXAMPLE_TYPE_CALLABLE_MEDIA_STREAM, \
- ExampleCallableMediaStream))
-#define EXAMPLE_CALLABLE_MEDIA_STREAM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), EXAMPLE_TYPE_CALLABLE_MEDIA_STREAM, \
- ExampleCallableMediaStreamClass))
-#define EXAMPLE_IS_CALLABLE_MEDIA_STREAM(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXAMPLE_TYPE_CALLABLE_MEDIA_STREAM))
-#define EXAMPLE_IS_CALLABLE_MEDIA_STREAM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), EXAMPLE_TYPE_CALLABLE_MEDIA_STREAM))
-#define EXAMPLE_CALLABLE_MEDIA_STREAM_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), EXAMPLE_TYPE_CALLABLE_MEDIA_STREAM, \
- ExampleCallableMediaStreamClass))
-
-struct _ExampleCallableMediaStreamClass {
- GObjectClass parent_class;
-
- ExampleCallableMediaStreamClassPrivate *priv;
-};
-
-struct _ExampleCallableMediaStream {
- GObject parent;
-
- ExampleCallableMediaStreamPrivate *priv;
-};
-
-void example_callable_media_stream_close (ExampleCallableMediaStream *self);
-gboolean example_callable_media_stream_change_direction (
- ExampleCallableMediaStream *self, TpMediaStreamDirection direction,
- GError **error);
-void example_callable_media_stream_accept_proposed_direction (
- ExampleCallableMediaStream *self);
-void example_callable_media_stream_connect (ExampleCallableMediaStream *self);
-
-/* This controls receiving emulated network events, so it wouldn't exist in
- * a real connection manager */
-void example_callable_media_stream_simulate_contact_agreed_to_send (
- ExampleCallableMediaStream *self);
-
-void example_callable_media_stream_receive_direction_request (
- ExampleCallableMediaStream *self, TpMediaStreamDirection direction);
-
-G_END_DECLS
-
-#endif
diff --git a/examples/cm/callable/protocol.h b/examples/cm/callable/protocol.h
deleted file mode 100644
index 0a5e0a795..000000000
--- a/examples/cm/callable/protocol.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * protocol.h - header for an example Protocol
- * Copyright © 2007-2010 Collabora Ltd.
- *
- * 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_PROTOCOL_H
-#define EXAMPLE_CALLABLE_PROTOCOL_H
-
-#include <glib-object.h>
-#include <telepathy-glib/base-protocol.h>
-
-G_BEGIN_DECLS
-
-typedef struct _ExampleCallableProtocol
- ExampleCallableProtocol;
-typedef struct _ExampleCallableProtocolPrivate
- ExampleCallableProtocolPrivate;
-typedef struct _ExampleCallableProtocolClass
- ExampleCallableProtocolClass;
-typedef struct _ExampleCallableProtocolClassPrivate
- ExampleCallableProtocolClassPrivate;
-
-struct _ExampleCallableProtocolClass {
- TpBaseProtocolClass parent_class;
-
- ExampleCallableProtocolClassPrivate *priv;
-};
-
-struct _ExampleCallableProtocol {
- TpBaseProtocol parent;
-
- ExampleCallableProtocolPrivate *priv;
-};
-
-GType example_callable_protocol_get_type (void);
-
-#define EXAMPLE_TYPE_CALLABLE_PROTOCOL \
- (example_callable_protocol_get_type ())
-#define EXAMPLE_CALLABLE_PROTOCOL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
- EXAMPLE_TYPE_CALLABLE_PROTOCOL, \
- ExampleCallableProtocol))
-#define EXAMPLE_CALLABLE_PROTOCOL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), \
- EXAMPLE_TYPE_CALLABLE_PROTOCOL, \
- ExampleCallableProtocolClass))
-#define EXAMPLE_IS_CALLABLE_PROTOCOL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
- EXAMPLE_TYPE_CALLABLE_PROTOCOL))
-#define EXAMPLE_IS_CALLABLE_PROTOCOL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), \
- EXAMPLE_TYPE_CALLABLE_PROTOCOL))
-#define EXAMPLE_CALLABLE_PROTOCOL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), \
- EXAMPLE_TYPE_CALLABLE_PROTOCOL, \
- ExampleCallableProtocolClass))
-
-gboolean example_callable_protocol_check_contact_id (const gchar *id,
- gchar **normal,
- GError **error);
-
-G_END_DECLS
-
-#endif