[Telepathy-commits] [telepathy-qt4/master] Merge 'callable' example CM from telepathy-glib 0.7.27.
Andre Moreira Magalhaes (andrunko)
andre.magalhaes at collabora.co.uk
Thu Mar 19 08:44:04 PDT 2009
---
tests/lib/callable/conn.c | 21 +++
tests/lib/callable/media-channel.c | 290 +++++++++++++++++++++++++++++-------
tests/lib/callable/media-manager.c | 58 +++++++-
tests/lib/callable/media-stream.c | 113 ++++++++++++++
tests/lib/callable/media-stream.h | 5 +
5 files changed, 432 insertions(+), 55 deletions(-)
diff --git a/tests/lib/callable/conn.c b/tests/lib/callable/conn.c
index 34a3530..027cc0b 100644
--- a/tests/lib/callable/conn.c
+++ b/tests/lib/callable/conn.c
@@ -50,6 +50,14 @@ enum
N_PROPS
};
+enum
+{
+ SIGNAL_AVAILABLE,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS] = { 0 };
+
struct _ExampleCallableConnectionPrivate
{
gchar *account;
@@ -333,6 +341,12 @@ set_own_status (GObject *object,
(gpointer) status);
tp_presence_mixin_emit_presence_update (object, presences);
g_hash_table_destroy (presences);
+
+ if (!self->priv->away)
+ {
+ g_signal_emit (self, signals[SIGNAL_AVAILABLE], 0, message);
+ }
+
return TRUE;
}
@@ -392,6 +406,13 @@ 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
+ * available */
+ signals[SIGNAL_AVAILABLE] = g_signal_new ("available",
+ G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
tp_contacts_mixin_class_init (object_class,
G_STRUCT_OFFSET (ExampleCallableConnectionClass, contacts_mixin));
tp_presence_mixin_class_init (object_class,
diff --git a/tests/lib/callable/media-channel.c b/tests/lib/callable/media-channel.c
index 5f305cf..d6d693d 100644
--- a/tests/lib/callable/media-channel.c
+++ b/tests/lib/callable/media-channel.c
@@ -37,6 +37,8 @@
#include "media-stream.h"
+#include <string.h>
+
#include <telepathy-glib/base-connection.h>
#include <telepathy-glib/channel-iface.h>
#include <telepathy-glib/dbus.h>
@@ -75,6 +77,8 @@ enum
PROP_CHANNEL_DESTROYED,
PROP_CHANNEL_PROPERTIES,
PROP_SIMULATION_DELAY,
+ PROP_INITIAL_AUDIO,
+ PROP_INITIAL_VIDEO,
N_PROPS
};
@@ -108,6 +112,8 @@ struct _ExampleCallableMediaChannelPrivate
GHashTable *streams;
gboolean locally_requested;
+ gboolean initial_audio;
+ gboolean initial_video;
gboolean disposed;
};
@@ -128,6 +134,10 @@ example_callable_media_channel_init (ExampleCallableMediaChannel *self)
NULL, g_object_unref);
}
+static ExampleCallableMediaStream *example_callable_media_channel_add_stream (
+ ExampleCallableMediaChannel *self, TpMediaStreamType media_type,
+ gboolean locally_requested);
+
static void
constructed (GObject *object)
{
@@ -206,9 +216,32 @@ constructed (GObject *object)
*/
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 (!(self->priv->locally_requested && self->priv->initial_audio));
+ g_assert (!(self->priv->locally_requested && self->priv->initial_video));
+
if (!self->priv->locally_requested)
{
- /* FIXME: act on any streams that the remote peer has already enabled */
+ /* 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);
+ }
}
}
@@ -296,6 +329,14 @@ get_property (GObject *object,
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;
@@ -347,6 +388,14 @@ set_property (GObject *object,
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;
@@ -361,24 +410,30 @@ example_callable_media_channel_close (ExampleCallableMediaChannel *self,
if (self->priv->progress != PROGRESS_ENDED)
{
TpIntSet *everyone;
- const gchar *send_reason;
self->priv->progress = PROGRESS_ENDED;
- /* 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)
+ if (actor == self->group.self_handle)
{
- case TP_CHANNEL_GROUP_CHANGE_REASON_BUSY:
- send_reason = "<user-is-busy/>";
- break;
+ const gchar *send_reason;
- case TP_CHANNEL_GROUP_CHANGE_REASON_NO_ANSWER:
- send_reason = "<no-answer/>";
- break;
+ /* 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;
- default:
- send_reason = "<call-terminated/>";
+ 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 (self->priv->handle);
@@ -392,7 +447,6 @@ example_callable_media_channel_close (ExampleCallableMediaChannel *self,
reason);
tp_intset_destroy (everyone);
- g_message ("SIGNALLING: send: Terminating call: %s", send_reason);
g_signal_emit (self, signals[SIGNAL_CALL_TERMINATED], 0);
tp_svc_channel_emit_closed (self);
}
@@ -408,7 +462,7 @@ dispose (GObject *object)
self->priv->disposed = TRUE;
- example_callable_media_channel_close (self, 0,
+ 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);
@@ -453,10 +507,16 @@ add_member (GObject *object,
{
/* 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, self->priv->handle));
+ self->priv->progress = PROGRESS_ACTIVE;
+
tp_group_mixin_change_members (object, "",
set /* added */,
NULL /* nobody removed */,
@@ -464,6 +524,16 @@ add_member (GObject *object,
NULL /* nobody added to remote pending */,
member /* actor */, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
+ 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;
}
@@ -585,6 +655,20 @@ example_callable_media_channel_class_init (ExampleCallableMediaChannelClass *kla
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,
@@ -833,12 +917,32 @@ stream_state_changed_cb (ExampleCallableMediaStream *stream,
}
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, self->priv->handle,
+ 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;
/* if the call has been cancelled while we were waiting for the
* contact to answer, do nothing */
@@ -873,9 +977,101 @@ simulate_contact_answered_cb (gpointer p)
example_callable_media_stream_connect (v);
}
+ 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)
+{
+ 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, self->priv->handle,
+ 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++;
+
+ if (locally_requested)
+ {
+ g_message ("SIGNALLING: send: new %s stream",
+ media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video");
+ }
+
+ stream = g_object_new (EXAMPLE_TYPE_CALLABLE_MEDIA_STREAM,
+ "channel", self,
+ "id", id,
+ "handle", self->priv->handle,
+ "type", media_type,
+ NULL);
+
+ g_hash_table_insert (self->priv->streams, GUINT_TO_POINTER (id), stream);
+
+ tp_svc_channel_type_streamed_media_emit_stream_added (self, id,
+ self->priv->handle, media_type);
+
+ 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 (locally_requested)
+ {
+ /* the local user wants this stream to be bidirectional (which
+ * requires remote acknowledgement */
+ example_callable_media_stream_change_direction (stream,
+ TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, NULL);
+ }
+ else
+ {
+ /* the remote user wants this stream to be bidirectional (which
+ * requires local acknowledgement) */
+ example_callable_media_stream_receive_direction_request (stream,
+ TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL);
+ }
+
+ if (self->priv->progress == PROGRESS_ACTIVE)
+ {
+ example_callable_media_stream_connect (stream);
+ }
+
+ return stream;
+}
+
static void
media_request_streams (TpSvcChannelTypeStreamedMedia *iface,
guint contact_handle,
@@ -930,11 +1126,11 @@ media_request_streams (TpSvcChannelTypeStreamedMedia *iface,
guint media_type = g_array_index (media_types, guint, i);
ExampleCallableMediaStream *stream;
GValueArray *info;
- guint id = self->priv->next_stream_id++;
if (self->priv->progress < PROGRESS_CALLING)
{
TpIntSet *peer_set = tp_intset_new_containing (self->priv->handle);
+ const gchar *peer;
g_message ("SIGNALLING: send: new streamed media call");
self->priv->progress = PROGRESS_CALLING;
@@ -950,45 +1146,33 @@ media_request_streams (TpSvcChannelTypeStreamedMedia *iface,
tp_intset_destroy (peer_set);
/* In this example there is no real contact, so just simulate them
- * answering after a short time */
- /* FIXME: define a special contact who never answers, and if it's
- * that contact, don't add this timeout */
- g_timeout_add_full (G_PRIORITY_DEFAULT, self->priv->simulation_delay,
- simulate_contact_answered_cb, g_object_ref (self),
- g_object_unref);
+ * 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);
+ }
}
- g_message ("SIGNALLING: send: new %s stream",
- media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video");
-
- stream = g_object_new (EXAMPLE_TYPE_CALLABLE_MEDIA_STREAM,
- "channel", self,
- "id", id,
- "handle", self->priv->handle,
- "type", media_type,
- NULL);
-
- g_hash_table_insert (self->priv->streams, GUINT_TO_POINTER (id), stream);
-
- tp_svc_channel_type_streamed_media_emit_stream_added (self, id,
- self->priv->handle, media_type);
-
- 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);
-
- /* newly requested streams start off in a "we want to be bidirectional"
- * state */
- example_callable_media_stream_change_direction (stream,
- TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, NULL);
-
- if (self->priv->progress == PROGRESS_ACTIVE)
- {
- example_callable_media_stream_connect (stream);
- }
+ stream = example_callable_media_channel_add_stream (self, media_type,
+ TRUE);
g_object_get (stream,
"stream-info", &info,
diff --git a/tests/lib/callable/media-manager.c b/tests/lib/callable/media-manager.c
index 7f9372b..c5548eb 100644
--- a/tests/lib/callable/media-manager.c
+++ b/tests/lib/callable/media-manager.c
@@ -62,6 +62,7 @@ struct _ExampleCallableMediaManagerPrivate
guint next_channel_index;
gulong status_changed_id;
+ gulong available_id;
};
static void
@@ -74,6 +75,7 @@ example_callable_media_manager_init (ExampleCallableMediaManager *self)
self->priv->conn = NULL;
self->priv->channels = NULL;
self->priv->status_changed_id = 0;
+ self->priv->available_id = 0;
}
static void
@@ -89,6 +91,13 @@ example_callable_media_manager_close_all (ExampleCallableMediaManager *self)
g_list_free (tmp);
}
+ if (self->priv->available_id != 0)
+ {
+ g_signal_handler_disconnect (self->priv->conn,
+ self->priv->available_id);
+ self->priv->available_id = 0;
+ }
+
if (self->priv->status_changed_id != 0)
{
g_signal_handler_disconnect (self->priv->conn,
@@ -177,6 +186,44 @@ 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 gboolean
+simulate_incoming_call_cb (gpointer p)
+{
+ ExampleCallableMediaManager *self = p;
+ TpHandleRepoIface *contact_repo;
+ TpHandle caller;
+
+ /* do nothing if we've been disconnected while waiting for the contact to
+ * call us */
+ if (self->priv->available_id == 0)
+ return FALSE;
+
+ /* We're called by someone whose ID on the IM service is "caller" */
+ contact_repo = tp_base_connection_get_handles (self->priv->conn,
+ TP_HANDLE_TYPE_CONTACT);
+ caller = tp_handle_ensure (contact_repo, "caller", NULL, NULL);
+
+ new_channel (self, caller, caller, NULL, TRUE, FALSE);
+
+ return FALSE;
+}
+
+/* Whenever our presence changes from away to available, and whenever our
+ * presence message changes while remaining available, simulate a call from
+ * a contact */
+static void
+available_cb (GObject *conn G_GNUC_UNUSED,
+ const gchar *message,
+ ExampleCallableMediaManager *self)
+{
+ g_timeout_add_full (G_PRIORITY_DEFAULT, self->priv->simulation_delay,
+ simulate_incoming_call_cb, g_object_ref (self), g_object_unref);
+}
+
static void
constructed (GObject *object)
{
@@ -191,6 +238,9 @@ constructed (GObject *object)
self->priv->status_changed_id = g_signal_connect (self->priv->conn,
"status-changed", (GCallback) status_changed_cb, self);
+
+ self->priv->available_id = g_signal_connect (self->priv->conn,
+ "available", (GCallback) available_cb, self);
}
static void
@@ -250,7 +300,9 @@ static ExampleCallableMediaChannel *
new_channel (ExampleCallableMediaManager *self,
TpHandle handle,
TpHandle initiator,
- gpointer request_token)
+ gpointer request_token,
+ gboolean initial_audio,
+ gboolean initial_video)
{
ExampleCallableMediaChannel *chan;
gchar *object_path;
@@ -268,6 +320,8 @@ new_channel (ExampleCallableMediaManager *self,
"initiator-handle", initiator,
"requested", (self->priv->conn->self_handle == initiator),
"simulation-delay", self->priv->simulation_delay,
+ "initial-audio", initial_audio,
+ "initial-video", initial_video,
NULL);
g_free (object_path);
@@ -387,7 +441,7 @@ example_callable_media_manager_request (ExampleCallableMediaManager *self,
}
new_channel (self, handle, self->priv->conn->self_handle,
- request_token);
+ request_token, FALSE, FALSE);
return TRUE;
error:
diff --git a/tests/lib/callable/media-stream.c b/tests/lib/callable/media-stream.c
index 43f9ccd..2b59d4b 100644
--- a/tests/lib/callable/media-stream.c
+++ b/tests/lib/callable/media-stream.c
@@ -370,6 +370,23 @@ example_callable_media_stream_close (ExampleCallableMediaStream *self)
}
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)
{
@@ -504,3 +521,99 @@ example_callable_media_stream_connect (ExampleCallableMediaStream *self)
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/tests/lib/callable/media-stream.h b/tests/lib/callable/media-stream.h
index 5f5d916..e7ec048 100644
--- a/tests/lib/callable/media-stream.h
+++ b/tests/lib/callable/media-stream.h
@@ -71,6 +71,8 @@ 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
@@ -78,6 +80,9 @@ void example_callable_media_stream_connect (ExampleCallableMediaStream *self);
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
--
1.5.6.5
More information about the telepathy-commits
mailing list