summaryrefslogtreecommitdiff
path: root/rakia/media-stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'rakia/media-stream.c')
-rw-r--r--rakia/media-stream.c1532
1 files changed, 0 insertions, 1532 deletions
diff --git a/rakia/media-stream.c b/rakia/media-stream.c
deleted file mode 100644
index 3b62353..0000000
--- a/rakia/media-stream.c
+++ /dev/null
@@ -1,1532 +0,0 @@
-/*
- * sip-media-stream.c - Source for RakiaMediaStream
- * Copyright (C) 2006 Collabora Ltd.
- * Copyright (C) 2006-2010 Nokia Corporation
- * @author Kai Vehmanen <first.surname@nokia.com>
- * @author Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
- *
- * Based on telepathy-gabble implementation (gabble-media-stream).
- * @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
- *
- * This work 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 work 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 work; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-#include "rakia/media-stream.h"
-
-#include <dbus/dbus-glib.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-generic.h>
-#include <telepathy-glib/svc-media-interfaces.h>
-#include <telepathy-glib/util.h>
-
-#include "config.h"
-
-#include <rakia/codec-param-formats.h>
-
-
-#include "rakia/media-session.h"
-#include "rakia/sip-session.h"
-
-#include <sofia-sip/msg_parser.h>
-
-#include "signals-marshal.h"
-
-#define DEBUG_FLAG RAKIA_DEBUG_MEDIA
-#include "rakia/debug.h"
-
-
-#define same_boolean(old, new) ((!(old)) == (!(new)))
-
-
-#ifdef ENABLE_DEBUG
-
-#define STREAM_DEBUG(stream, format, ...) \
- rakia_log (DEBUG_FLAG, G_LOG_LEVEL_DEBUG, "stream %u: " format, \
- (stream)->priv->id,##__VA_ARGS__)
-
-#define STREAM_MESSAGE(stream, format, ...) \
- rakia_log (DEBUG_FLAG, G_LOG_LEVEL_MESSAGE, "stream %u: " format, \
- (stream)->priv->id,##__VA_ARGS__)
-
-#else
-
-#define STREAM_DEBUG(stream, format, ...) G_STMT_START { } G_STMT_END
-#define STREAM_MESSAGE(stream, format, ...) G_STMT_START { } G_STMT_END
-
-#endif
-
-
-static void stream_handler_iface_init (gpointer, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE(RakiaMediaStream,
- rakia_media_stream,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_MEDIA_STREAM_HANDLER,
- stream_handler_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
- tp_dbus_properties_mixin_iface_init);
- )
-
-/* signal enum */
-enum
-{
- SIG_READY,
- SIG_SUPPORTED_CODECS,
- SIG_STATE_CHANGED,
- SIG_DIRECTION_CHANGED,
- SIG_LOCAL_MEDIA_UPDATED,
- SIG_UNHOLD_FAILURE,
-
- SIG_LAST_SIGNAL
-};
-
-static guint signals[SIG_LAST_SIGNAL] = {0};
-
-/* properties */
-enum
-{
- PROP_MEDIA_SESSION = 1,
- PROP_DBUS_DAEMON,
- PROP_OBJECT_PATH,
- PROP_ID,
- PROP_MEDIA_TYPE,
- PROP_SIP_MEDIA,
- PROP_STATE,
- PROP_DIRECTION,
- PROP_PENDING_SEND_FLAGS,
- PROP_HOLD_STATE,
- PROP_CREATED_LOCALLY,
- PROP_NAT_TRAVERSAL,
- PROP_STUN_SERVERS,
- PROP_RELAY_INFO,
- LAST_PROPERTY
-};
-
-static GPtrArray *rakia_media_stream_relay_info_empty = NULL;
-
-/* private structure */
-struct _RakiaMediaStreamPrivate
-{
- TpDBusDaemon *dbus_daemon;
- RakiaMediaSession *session; /* see gobj. prop. 'media-session' */
- gchar *object_path; /* see gobj. prop. 'object-path' */
- RakiaSipMedia *media;
- guint id; /* see gobj. prop. 'id' */
- guint media_type; /* see gobj. prop. 'media-type' */
- guint state; /* see gobj. prop. 'state' */
- guint direction; /* see gobj. prop. 'direction' */
- guint pending_send_flags; /* see gobj. prop. 'pending-send-flags' */
- gboolean hold_state; /* see gobj. prop. 'hold-state' */
- gboolean created_locally; /* see gobj. prop. 'created-locally' */
-
- guint remote_candidate_counter;
- gchar *remote_candidate_id;
-
- gchar *native_candidate_id;
-
- gboolean ready_received; /* our ready method has been called */
- gboolean playing; /* stream set to playing */
- gboolean sending; /* stream set to sending */
- gboolean pending_remote_receive; /* TRUE if remote is to agree to receive media */
- gboolean native_cands_prepared; /* all candidates discovered */
- gboolean native_codecs_prepared; /* all codecs discovered */
- gboolean push_remote_cands_pending; /* SetRemoteCandidates emission is pending */
- gboolean push_remote_codecs_pending; /* SetRemoteCodecs emission is pending */
- gboolean codec_intersect_pending; /* codec intersection is pending */
- gboolean requested_hold_state; /* hold state last requested from the stream handler */
- gboolean dispose_has_run;
-};
-
-#define RAKIA_MEDIA_STREAM_GET_PRIVATE(stream) ((stream)->priv)
-
-static void push_remote_codecs (RakiaMediaStream *stream);
-static void push_remote_candidates (RakiaMediaStream *stream);
-static void priv_update_sending (RakiaMediaStream *stream,
- TpMediaStreamDirection direction);
-static void priv_emit_local_ready (RakiaMediaStream *stream);
-
-/***********************************************************************
- * Set: Gobject interface
- ***********************************************************************/
-
-static void
-rakia_media_stream_init (RakiaMediaStream *self)
-{
- RakiaMediaStreamPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE ((self),
- RAKIA_TYPE_MEDIA_STREAM, RakiaMediaStreamPrivate);
-
- self->priv = priv;
-}
-
-static void
-rakia_media_stream_constructed (GObject *obj)
-{
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (
- RAKIA_MEDIA_STREAM (obj));
- GObjectClass *parent_object_class =
- G_OBJECT_CLASS (rakia_media_stream_parent_class);
-
- /* call base class method */
- if (parent_object_class->constructed != NULL)
- parent_object_class->constructed (obj);
-
- /* XXX: overloading the remote pending send flag to check
- * if this is a locally offered stream. The code creating such streams
- * always sets the flag, because the remote end is supposed to decide
- * whether it wants to send.
- * This may look weird during a local hold. However, the pending flag
- * will be harmlessly cleared once the offer-answer is complete. */
- if ((priv->direction & TP_MEDIA_STREAM_DIRECTION_SEND) != 0
- && (priv->pending_send_flags & TP_MEDIA_STREAM_PENDING_REMOTE_SEND) != 0)
- {
- /* Block sending until the stream is remotely accepted */
- priv->pending_remote_receive = TRUE;
- }
-
- g_signal_connect_object (priv->media, "remote-candidates-updated",
- G_CALLBACK (push_remote_candidates), obj, G_CONNECT_SWAPPED);
- g_signal_connect_object (priv->media, "remote-codecs-updated",
- G_CALLBACK (push_remote_codecs), obj, G_CONNECT_SWAPPED);
-
- /* go for the bus */
- g_assert (TP_IS_DBUS_DAEMON (priv->dbus_daemon));
- tp_dbus_daemon_register_object (priv->dbus_daemon, priv->object_path, obj);
-}
-
-static void
-rakia_media_stream_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- RakiaMediaStream *stream = RAKIA_MEDIA_STREAM (object);
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (stream);
-
- switch (property_id)
- {
- case PROP_DBUS_DAEMON:
- g_value_set_object (value, priv->dbus_daemon);
- break;
- case PROP_MEDIA_SESSION:
- g_value_set_object (value, priv->session);
- break;
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_ID:
- g_value_set_uint (value, priv->id);
- break;
- case PROP_MEDIA_TYPE:
- g_value_set_uint (value, priv->media_type);
- break;
- case PROP_SIP_MEDIA:
- g_value_set_object (value, priv->media);
- break;
- case PROP_STATE:
- g_value_set_uint (value, priv->state);
- break;
- case PROP_DIRECTION:
- g_value_set_uint (value, priv->direction);
- break;
- case PROP_PENDING_SEND_FLAGS:
- g_value_set_uint (value, priv->pending_send_flags);
- break;
- case PROP_HOLD_STATE:
- g_value_set_boolean (value, priv->hold_state);
- break;
- case PROP_CREATED_LOCALLY:
- g_value_set_boolean (value, priv->created_locally);
- break;
- case PROP_NAT_TRAVERSAL:
- g_value_set_static_string (value, "none");
- break;
- case PROP_STUN_SERVERS:
- g_return_if_fail (priv->session != NULL);
- g_object_get_property (G_OBJECT (priv->session), "stun-servers", value);
- break;
- case PROP_RELAY_INFO:
- g_value_set_static_boxed (value, rakia_media_stream_relay_info_empty);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-rakia_media_stream_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- RakiaMediaStream *stream = RAKIA_MEDIA_STREAM (object);
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (stream);
-
- switch (property_id)
- {
- case PROP_DBUS_DAEMON:
- g_assert (priv->dbus_daemon == NULL); /* construct-only */
- priv->dbus_daemon = g_value_dup_object (value);
- break;
- case PROP_MEDIA_SESSION:
- priv->session = g_value_get_object (value);
- break;
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_ID:
- priv->id = g_value_get_uint (value);
- break;
- case PROP_MEDIA_TYPE:
- priv->media_type = g_value_get_uint (value);
- break;
- case PROP_SIP_MEDIA:
- priv->media = g_value_dup_object (value);
- break;
- case PROP_STATE:
- priv->state = g_value_get_uint (value);
- break;
- case PROP_DIRECTION:
- priv->direction = g_value_get_uint (value);
- break;
- case PROP_PENDING_SEND_FLAGS:
- priv->pending_send_flags = g_value_get_uint (value);
- break;
- case PROP_HOLD_STATE:
- priv->hold_state = g_value_get_boolean (value);
- break;
- case PROP_CREATED_LOCALLY:
- priv->created_locally = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void rakia_media_stream_dispose (GObject *object);
-static void rakia_media_stream_finalize (GObject *object);
-
-static void
-rakia_media_stream_class_init (RakiaMediaStreamClass *klass)
-{
- static TpDBusPropertiesMixinPropImpl stream_handler_props[] = {
- { "CreatedLocally", "created-locally", NULL },
- { "NATTraversal", "nat-traversal", NULL },
- { "STUNServers", "stun-servers", NULL },
- { "RelayInfo", "relay-info", NULL },
- { NULL }
- };
-
- static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
- { TP_IFACE_MEDIA_STREAM_HANDLER,
- tp_dbus_properties_mixin_getter_gobject_properties,
- NULL,
- stream_handler_props,
- },
- { NULL }
- };
-
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GType stream_type = G_OBJECT_CLASS_TYPE (klass);
- GParamSpec *param_spec;
-
- g_type_class_add_private (klass, sizeof (RakiaMediaStreamPrivate));
-
- object_class->constructed = rakia_media_stream_constructed;
-
- object_class->get_property = rakia_media_stream_get_property;
- object_class->set_property = rakia_media_stream_set_property;
-
- object_class->dispose = rakia_media_stream_dispose;
- object_class->finalize = rakia_media_stream_finalize;
-
- param_spec = g_param_spec_object ("dbus-daemon", "TpDBusDaemon",
- "Connection to D-Bus.", TP_TYPE_DBUS_DAEMON,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_DBUS_DAEMON, param_spec);
-
- param_spec = g_param_spec_object ("media-session", "RakiaMediaSession object",
- "SIP media session object that owns this media stream object.",
- RAKIA_TYPE_MEDIA_SESSION,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_MEDIA_SESSION, param_spec);
-
- param_spec = g_param_spec_string ("object-path", "D-Bus object path",
- "The D-Bus object path used for this object on the bus.",
- NULL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_OBJECT_PATH, param_spec);
-
- param_spec = g_param_spec_uint ("id", "Stream ID",
- "A stream number for the stream used in the D-Bus API.",
- 0, G_MAXUINT,
- 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 ("media-type", "Stream media type",
- "A constant indicating which media type the stream carries.",
- TP_MEDIA_STREAM_TYPE_AUDIO, TP_MEDIA_STREAM_TYPE_VIDEO,
- TP_MEDIA_STREAM_TYPE_AUDIO,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_MEDIA_TYPE, param_spec);
-
-
- param_spec = g_param_spec_object ("sip-media", "RakiaSipMedia object",
- "SIP media session object that owns this media stream object.",
- RAKIA_TYPE_MEDIA_SESSION,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_MEDIA_SESSION, param_spec);
-
-
- param_spec = g_param_spec_uint ("state", "Connection state",
- "Connection state of the media stream",
- TP_MEDIA_STREAM_STATE_DISCONNECTED, TP_MEDIA_STREAM_STATE_CONNECTED,
- TP_MEDIA_STREAM_STATE_DISCONNECTED,
- G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_STATE, param_spec);
-
- /* We don't change the following two as individual properties
- * after construction, use rakia_media_stream_set_direction() */
-
- param_spec = g_param_spec_uint ("direction", "Stream direction",
- "A value indicating the current direction of the stream",
- TP_MEDIA_STREAM_DIRECTION_NONE, TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL,
- TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_DIRECTION, param_spec);
-
- param_spec = g_param_spec_uint ("pending-send-flags", "Pending send flags",
- "Flags indicating the current pending send state of the stream",
- 0,
- TP_MEDIA_STREAM_PENDING_LOCAL_SEND | TP_MEDIA_STREAM_PENDING_REMOTE_SEND,
- 0,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_PENDING_SEND_FLAGS,
- param_spec);
-
- param_spec = g_param_spec_boolean ("hold-state", "Hold state",
- "Hold state of the media stream as reported by the stream engine",
- FALSE,
- G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_HOLD_STATE,
- param_spec);
-
- param_spec = g_param_spec_boolean ("created-locally", "Created locally?",
- "True if this stream was created by the local user", FALSE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CREATED_LOCALLY,
- param_spec);
-
- param_spec = g_param_spec_string ("nat-traversal", "NAT traversal",
- "NAT traversal mechanism for this stream", NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_NAT_TRAVERSAL,
- param_spec);
-
- param_spec = g_param_spec_boxed ("stun-servers", "STUN servers",
- "Array of IP address-port pairs for available STUN servers",
- TP_ARRAY_TYPE_SOCKET_ADDRESS_IP_LIST,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_STUN_SERVERS, param_spec);
-
- param_spec = g_param_spec_boxed ("relay-info", "Relay info",
- "Array of mappings containing relay server information",
- TP_ARRAY_TYPE_STRING_VARIANT_MAP_LIST,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_RELAY_INFO, param_spec);
-
- rakia_media_stream_relay_info_empty = g_ptr_array_new ();
-
- /* signals not exported by DBus interface */
- signals[SIG_READY] =
- g_signal_new ("ready",
- stream_type,
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- signals[SIG_SUPPORTED_CODECS] =
- g_signal_new ("supported-codecs",
- stream_type,
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT,
- G_TYPE_NONE, 1, G_TYPE_UINT);
-
- signals[SIG_STATE_CHANGED] =
- g_signal_new ("state-changed",
- stream_type,
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT,
- G_TYPE_NONE, 1, G_TYPE_UINT);
-
- signals[SIG_DIRECTION_CHANGED] =
- g_signal_new ("direction-changed",
- stream_type,
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- _rakia_marshal_VOID__UINT_UINT,
- G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
-
- signals[SIG_LOCAL_MEDIA_UPDATED] =
- g_signal_new ("local-media-updated",
- stream_type,
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- signals[SIG_UNHOLD_FAILURE] =
- g_signal_new ("unhold-failure",
- stream_type,
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- klass->dbus_props_class.interfaces = prop_interfaces;
- tp_dbus_properties_mixin_class_init (object_class,
- G_STRUCT_OFFSET (RakiaMediaStreamClass, dbus_props_class));
-}
-
-void
-rakia_media_stream_dispose (GObject *object)
-{
- RakiaMediaStream *self = RAKIA_MEDIA_STREAM (object);
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (self);
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- tp_clear_object (&priv->media);
- tp_clear_object (&priv->dbus_daemon);
-
- if (G_OBJECT_CLASS (rakia_media_stream_parent_class)->dispose)
- G_OBJECT_CLASS (rakia_media_stream_parent_class)->dispose (object);
-
- DEBUG ("exit");
-}
-
-void
-rakia_media_stream_finalize (GObject *object)
-{
- RakiaMediaStream *self = RAKIA_MEDIA_STREAM (object);
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (self);
-
- /* free any data held directly by the object here */
- g_free (priv->object_path);
-
-
- g_free (priv->native_candidate_id);
- g_free (priv->remote_candidate_id);
-
- G_OBJECT_CLASS (rakia_media_stream_parent_class)->finalize (object);
-
- DEBUG ("exit");
-}
-
-/***********************************************************************
- * Set: Media.StreamHandler interface implementation (same for 0.12/0.13???)
- ***********************************************************************/
-
-/**
- * rakia_media_stream_error
- *
- * Implements DBus method Error
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-rakia_media_stream_error (TpSvcMediaStreamHandler *iface,
- guint errno,
- const gchar *message,
- DBusGMethodInvocation *context)
-{
- RakiaMediaStream *self = RAKIA_MEDIA_STREAM (iface);
-
- STREAM_DEBUG (self, "StreamHandler.Error called: %u %s", errno, message);
-
- rakia_media_stream_close (self);
-
- tp_svc_media_stream_handler_return_from_error (context);
-}
-
-/**
- * rakia_media_stream_native_candidates_prepared
- *
- * Implements DBus method NativeCandidatesPrepared
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-rakia_media_stream_native_candidates_prepared (TpSvcMediaStreamHandler *iface,
- DBusGMethodInvocation *context)
-{
- /* purpose: "Informs the connection manager that all possible native candisates
- * have been discovered for the moment."
- */
-
- RakiaMediaStream *obj = RAKIA_MEDIA_STREAM (iface);
- RakiaMediaStreamPrivate *priv = obj->priv;
-
- STREAM_DEBUG(obj, "Media.StreamHandler.NativeCandidatesPrepared called");
-
- priv->native_cands_prepared = TRUE;
-
- rakia_sip_media_local_candidates_prepared (priv->media);
-
- if (priv->native_codecs_prepared)
- priv_emit_local_ready (obj);
-
- tp_svc_media_stream_handler_return_from_native_candidates_prepared (context);
-}
-
-
-/**
- * rakia_media_stream_new_active_candidate_pair
- *
- * Implements DBus method NewActiveCandidatePair
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-rakia_media_stream_new_active_candidate_pair (TpSvcMediaStreamHandler *iface,
- const gchar *native_candidate_id,
- const gchar *remote_candidate_id,
- DBusGMethodInvocation *context)
-{
- RakiaMediaStream *self = RAKIA_MEDIA_STREAM (iface);
- RakiaMediaStreamPrivate *priv = self->priv;
-
- STREAM_DEBUG (self, "stream engine reported new active candidate pair %s-%s",
- native_candidate_id, remote_candidate_id);
-
- if (priv->remote_candidate_id == NULL
- || strcmp (priv->remote_candidate_id, remote_candidate_id))
- {
- GError *err;
- err = g_error_new (TP_ERRORS,
- TP_ERROR_INVALID_ARGUMENT,
- "Remote candidate ID does not match the locally "
- "stored data");
- dbus_g_method_return_error (context, err);
- g_error_free (err);
- return;
- }
-
- tp_svc_media_stream_handler_return_from_new_active_candidate_pair (context);
-}
-
-
-/**
- * rakia_media_stream_new_native_candidate
- *
- * Implements DBus method NewNativeCandidate
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-rakia_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface,
- const gchar *candidate_id,
- const GPtrArray *transports,
- DBusGMethodInvocation *context)
-{
- RakiaMediaStream *obj = RAKIA_MEDIA_STREAM (iface);
- RakiaMediaStreamPrivate *priv;
- GValue transport = { 0, };
- guint i;
-
- priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (obj);
-
- g_return_if_fail (transports->len >= 1);
-
-
- /* Rate the preferability of the address */
- g_value_init (&transport, TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_TRANSPORT);
-
- for (i = 0; i < transports->len; i++)
- {
- RakiaSipCandidate *sipcandidate;
- guint tr_component;
- guint tr_proto = G_MAXUINT;
- gchar *tr_ip;
- guint tr_port;
- gdouble tr_preference;
-
- g_value_set_static_boxed (&transport,
- g_ptr_array_index (transports, i));
-
- /* Find the RTP component */
- dbus_g_type_struct_get (&transport,
- 0, &tr_component,
- 1, &tr_ip,
- 2, &tr_port,
- 3, &tr_proto,
- 6, &tr_preference,
- G_MAXUINT);
-
- if (tr_proto != TP_MEDIA_STREAM_BASE_PROTO_UDP)
- continue;
-
- sipcandidate = rakia_sip_candidate_new (tr_component,
- tr_ip, tr_port, candidate_id, (guint) tr_preference * 65536);
-
- g_free (tr_ip);
-
- rakia_sip_media_take_local_candidate (priv->media, sipcandidate);
- }
-
-
- STREAM_DEBUG(obj, "put native candidate '%s' into cache", candidate_id);
-
- tp_svc_media_stream_handler_return_from_new_native_candidate (context);
-}
-
-static void
-priv_set_local_codecs (RakiaMediaStream *self,
- const GPtrArray *codecs)
-{
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (self);
- GPtrArray *sipcodecs = g_ptr_array_new_with_free_func (
- (GDestroyNotify)rakia_sip_codec_free);
- GValue codec = { 0, };
- gchar *co_name = NULL;
- guint co_id;
- guint co_type;
- guint co_clockrate;
- guint co_channels;
- GHashTable *co_params = NULL;
- guint i;
- STREAM_DEBUG(self, "putting list of %d locally supported codecs into cache",
- codecs->len);
-
- g_value_init (&codec, TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CODEC);
-
- for (i = 0; i < codecs->len; i++)
- {
- RakiaSipCodec *sipcodec;
- GHashTableIter iter;
- gpointer key, value;
-
- g_value_set_static_boxed (&codec, g_ptr_array_index (codecs, i));
-
- dbus_g_type_struct_get (&codec,
- 0, &co_id,
- 1, &co_name,
- 2, &co_type,
- 3, &co_clockrate,
- 4, &co_channels,
- 5, &co_params,
- G_MAXUINT);
-
- sipcodec = rakia_sip_codec_new (co_id, co_name, co_clockrate,
- co_channels);
-
- g_hash_table_iter_init (&iter, co_params);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- rakia_sip_codec_add_param (sipcodec, key, value);
- }
-
- g_ptr_array_add (sipcodecs, sipcodec);
-
- g_free (co_name);
- co_name = NULL;
- g_hash_table_unref (co_params);
- co_params = NULL;
- }
-
- rakia_sip_media_take_local_codecs (priv->media, sipcodecs);
-
- priv->native_codecs_prepared = TRUE;
- if (priv->native_cands_prepared)
- priv_emit_local_ready (self);
-}
-
-static void
-rakia_media_stream_codecs_updated (TpSvcMediaStreamHandler *iface,
- const GPtrArray *codecs,
- DBusGMethodInvocation *context)
-{
- RakiaMediaStream *self = RAKIA_MEDIA_STREAM (iface);
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (self);
-
- if (!priv->native_codecs_prepared)
- {
- GError e = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "CodecsUpdated may not be called before codecs have been provided "
- "with SetLocalCodecs or Ready" };
-
- STREAM_DEBUG (self,
- "CodecsUpdated called before SetLocalCodecs or Ready");
-
- dbus_g_method_return_error (context, &e);
- }
- else
- {
- STREAM_DEBUG (self, "putting list of %d locally supported "
- "codecs from CodecsUpdated into cache", codecs->len);
- priv_set_local_codecs (self, codecs);
-
- if (priv->native_cands_prepared)
- g_signal_emit (self, signals[SIG_LOCAL_MEDIA_UPDATED], 0);
-
- tp_svc_media_stream_handler_return_from_codecs_updated (context);
- }
-}
-
-/**
- * rakia_media_stream_ready
- *
- * Implements DBus method Ready
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-rakia_media_stream_ready (TpSvcMediaStreamHandler *iface,
- const GPtrArray *codecs,
- DBusGMethodInvocation *context)
-{
- /* purpose: "Inform the connection manager that a client is ready to handle
- * this StreamHandler. Also provide it with info about all supported
- * codecs."
- *
- * - note, with SIP we don't send the invite just yet (we need
- * candidates first
- */
-
- RakiaMediaStream *obj = RAKIA_MEDIA_STREAM (iface);
- RakiaMediaStreamPrivate *priv = obj->priv;
-
- STREAM_DEBUG (obj, "Media.StreamHandler.Ready called");
-
- if (priv->ready_received)
- {
- STREAM_MESSAGE (obj, "Ready called more than once");
- tp_svc_media_stream_handler_return_from_ready (context);
- return;
- }
-
- priv->ready_received = TRUE;
-
- if (codecs->len != 0)
- priv_set_local_codecs (obj, codecs);
-
- /* Push the initial sending/playing state */
- tp_svc_media_stream_handler_emit_set_stream_playing (
- iface, priv->playing);
- tp_svc_media_stream_handler_emit_set_stream_sending (
- iface, priv->sending);
-
- if (priv->push_remote_cands_pending)
- {
- priv->push_remote_cands_pending = FALSE;
- push_remote_candidates (obj);
- }
- if (priv->push_remote_codecs_pending)
- {
- priv->push_remote_codecs_pending = FALSE;
- push_remote_codecs (obj);
- }
-
-
- rakia_media_stream_set_playing (obj, TRUE);
-
- tp_svc_media_stream_handler_return_from_ready (context);
-}
-
-static void
-rakia_media_stream_set_local_codecs (TpSvcMediaStreamHandler *iface,
- const GPtrArray *codecs,
- DBusGMethodInvocation *context)
-{
- priv_set_local_codecs (RAKIA_MEDIA_STREAM (iface), codecs);
- tp_svc_media_stream_handler_return_from_set_local_codecs (context);
-}
-
-/**
- * rakia_media_stream_stream_state
- *
- * Implements DBus method StreamState
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-rakia_media_stream_stream_state (TpSvcMediaStreamHandler *iface,
- guint state,
- DBusGMethodInvocation *context)
-{
- /* purpose: "Informs the connection manager of the stream's current state
- * State is as specified in *ChannelTypeStreamedMedia::GetStreams."
- *
- * - set the stream state for session
- */
-
- RakiaMediaStream *obj = RAKIA_MEDIA_STREAM (iface);
- RakiaMediaStreamPrivate *priv;
- priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (obj);
-
- if (priv->state != state)
- {
- STREAM_DEBUG (obj, "stream state change %u -> %u", priv->state, state);
- priv->state = state;
- g_signal_emit (obj, signals[SIG_STATE_CHANGED], 0, state);
- }
-
- tp_svc_media_stream_handler_return_from_stream_state (context);
-}
-
-/**
- * rakia_media_stream_supported_codecs
- *
- * Implements DBus method SupportedCodecs
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-rakia_media_stream_supported_codecs (TpSvcMediaStreamHandler *iface,
- const GPtrArray *codecs,
- DBusGMethodInvocation *context)
-{
- /* purpose: "Inform the connection manager of the supported codecs for this session.
- * This is called after the connection manager has emitted SetRemoteCodecs
- * to notify what codecs are supported by the peer, and will thus be an
- * intersection of all locally supported codecs (passed to Ready)
- * and those supported by the peer."
- *
- * - emit SupportedCodecs
- */
-
- RakiaMediaStream *self = RAKIA_MEDIA_STREAM (iface);
- RakiaMediaStreamPrivate *priv;
- priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (self);
-
- STREAM_DEBUG (self,
- "got codec intersection containing %u codecs from stream-engine",
- codecs->len);
-
- /* Save the local codecs, but avoid triggering a new
- * session update at this point. If the stream engine have changed any codec
- * parameters, it is supposed to follow up with CodecsUpdated. */
- priv_set_local_codecs (self, codecs);
-
- if (priv->codec_intersect_pending)
- {
- if (priv->push_remote_codecs_pending)
- {
- /* The remote codec list has been updated since the intersection
- * has started, plunge into a new intersection immediately */
- priv->push_remote_codecs_pending = FALSE;
- push_remote_codecs (self);
- }
- else
- {
- priv->codec_intersect_pending = FALSE;
- g_signal_emit (self, signals[SIG_SUPPORTED_CODECS], 0, codecs->len);
- }
- }
- else
- WARNING("SupportedCodecs called when no intersection is ongoing");
-
- tp_svc_media_stream_handler_return_from_supported_codecs (context);
-}
-
-static void
-rakia_media_stream_hold_state (TpSvcMediaStreamHandler *self,
- gboolean held,
- DBusGMethodInvocation *context)
-{
- g_object_set (self, "hold-state", held, NULL);
- tp_svc_media_stream_handler_return_from_hold_state (context);
-}
-
-static void
-rakia_media_stream_unhold_failure (TpSvcMediaStreamHandler *self,
- DBusGMethodInvocation *context)
-{
- /* Not doing anything to hold_state or requested_hold_state,
- * because the session is going to put all streams on hold after getting
- * the signal below */
-
- g_signal_emit (self, signals[SIG_UNHOLD_FAILURE], 0);
- tp_svc_media_stream_handler_return_from_unhold_failure (context);
-}
-
-/***********************************************************************
- * Helper functions follow (not based on generated templates)
- ***********************************************************************/
-
-guint
-rakia_media_stream_get_id (RakiaMediaStream *self)
-{
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (self);
- return priv->id;
-}
-
-guint
-rakia_media_stream_get_media_type (RakiaMediaStream *self)
-{
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (self);
- return priv->media_type;
-}
-
-void
-rakia_media_stream_close (RakiaMediaStream *self)
-{
- tp_svc_media_stream_handler_emit_close (self);
-}
-
-/*
- * Returns stream direction as requested by the latest local or remote
- * direction change.
- */
-static TpMediaStreamDirection
-priv_get_requested_direction (RakiaMediaStreamPrivate *priv)
-{
- TpMediaStreamDirection direction;
-
- direction = priv->direction;
- if ((priv->pending_send_flags & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) != 0)
- direction |= TP_MEDIA_STREAM_DIRECTION_SEND;
- return direction;
-}
-
-/**
- * Converts a sofia-sip media type enum to Telepathy media type.
- * See <sofia-sip/sdp.h> and <telepathy-constants.h>.
- *
- * @return G_MAXUINT if the media type cannot be mapped
- */
-guint
-rakia_tp_media_type (sdp_media_e sip_mtype)
-{
- switch (sip_mtype)
- {
- case sdp_media_audio: return TP_MEDIA_STREAM_TYPE_AUDIO;
- case sdp_media_video: return TP_MEDIA_STREAM_TYPE_VIDEO;
- default: return G_MAXUINT;
- }
-}
-
-
-/**
- * Sets the media state to playing or non-playing. When not playing,
- * received RTP packets may not be played locally.
- */
-void rakia_media_stream_set_playing (RakiaMediaStream *stream, gboolean playing)
-{
- RakiaMediaStreamPrivate *priv;
- priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (stream);
-
- if (same_boolean (priv->playing, playing))
- return;
-
- STREAM_DEBUG (stream, "set playing to %s", playing? "TRUE" : "FALSE");
-
- priv->playing = playing;
-
- if (priv->ready_received)
- tp_svc_media_stream_handler_emit_set_stream_playing (
- (TpSvcMediaStreamHandler *)stream, playing);
-}
-
-/**
- * Sets the media state to sending or non-sending. When not sending,
- * captured media are not sent over the network.
- */
-void
-rakia_media_stream_set_sending (RakiaMediaStream *stream, gboolean sending)
-{
- RakiaMediaStreamPrivate *priv;
- priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (stream);
-
- if (same_boolean(priv->sending, sending))
- return;
-
- STREAM_DEBUG (stream, "set sending to %s", sending? "TRUE" : "FALSE");
-
- priv->sending = sending;
-
- if (priv->ready_received)
- tp_svc_media_stream_handler_emit_set_stream_sending (
- (TpSvcMediaStreamHandler *)stream, sending);
-}
-
-static void
-priv_update_sending (RakiaMediaStream *stream,
- TpMediaStreamDirection direction)
-{
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (stream);
- gboolean sending = TRUE;
-
- /* XXX: the pending send flag check is probably an overkill
- * considering that effective sending direction and pending send should be
- * mutually exclusive */
- if ((direction & TP_MEDIA_STREAM_DIRECTION_SEND) == 0
- || priv->pending_remote_receive
- || (priv->pending_send_flags & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) != 0
- || !rakia_media_session_is_accepted (priv->session))
- {
- sending = FALSE;
- }
-
- rakia_media_stream_set_sending (stream, sending);
-}
-
-void
-rakia_media_stream_set_direction (RakiaMediaStream *stream,
- TpMediaStreamDirection direction,
- guint pending_send_mask)
-{
- RakiaMediaStreamPrivate *priv;
- guint pending_send_flags;
- TpMediaStreamDirection old_sdp_direction;
-
- priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (stream);
- pending_send_flags = priv->pending_send_flags & pending_send_mask;
-
- if ((direction & TP_MEDIA_STREAM_DIRECTION_SEND) == 0)
- {
- /* We won't be sending, clear the pending local send flag */
- pending_send_flags &= ~TP_MEDIA_STREAM_PENDING_LOCAL_SEND;
- }
- else if ((direction & TP_MEDIA_STREAM_DIRECTION_SEND & ~priv->direction) != 0)
- {
- /* We are requested to start sending, but... */
- if ((pending_send_mask
- & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) != 0)
- {
- /* ... but we need to confirm this with the client.
- * Clear the sending bit and set the pending send flag. */
- direction &= ~(guint)TP_MEDIA_STREAM_DIRECTION_SEND;
- pending_send_flags |= TP_MEDIA_STREAM_PENDING_LOCAL_SEND;
- }
- if ((pending_send_mask
- & TP_MEDIA_STREAM_PENDING_REMOTE_SEND) != 0
- && (priv->pending_send_flags
- & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) == 0)
- {
- g_assert ((priv_get_requested_direction (priv) & TP_MEDIA_STREAM_DIRECTION_SEND) == 0);
-
- /* ... but the caller wants to agree with the remote
- * end first. Block the stream handler from sending for now. */
- priv->pending_remote_receive = TRUE;
- }
- }
-
- if ((direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE) == 0)
- {
- /* We are not going to receive, clear the pending remote send flag */
- pending_send_flags &= ~TP_MEDIA_STREAM_PENDING_REMOTE_SEND;
- }
- else if ((direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE & ~priv->direction) != 0
- && (pending_send_mask
- & TP_MEDIA_STREAM_PENDING_REMOTE_SEND) != 0)
- {
- /* We're requested to start receiving, but the remote end did not
- * confirm if it will send. Set the pending send flag. */
- pending_send_flags |= TP_MEDIA_STREAM_PENDING_REMOTE_SEND;
- }
-
- if (priv->direction == direction
- && priv->pending_send_flags == pending_send_flags)
- return;
-
- old_sdp_direction = priv_get_requested_direction (priv);
-
- priv->direction = direction;
- priv->pending_send_flags = pending_send_flags;
-
- STREAM_DEBUG (stream, "set direction %u, pending send flags %u", priv->direction, priv->pending_send_flags);
-
- g_signal_emit (stream, signals[SIG_DIRECTION_CHANGED], 0,
- priv->direction, priv->pending_send_flags);
-
- priv_update_sending (stream, priv->direction);
-
- if (priv->native_cands_prepared
- && priv->native_codecs_prepared
- && priv_get_requested_direction (priv)
- != old_sdp_direction)
- g_signal_emit (stream, signals[SIG_LOCAL_MEDIA_UPDATED], 0);
-}
-
-/*
- * Clears the pending send flag(s) present in @pending_send_mask.
- * If #TP_MEDIA_STREAM_PENDING_LOCAL_SEND is thus cleared,
- * enable the sending bit in the stream direction.
- * If @pending_send_mask has #TP_MEDIA_STREAM_PENDING_REMOTE_SEND flag set,
- * also start sending if agreed by the stream direction.
- */
-void
-rakia_media_stream_apply_pending_direction (RakiaMediaStream *stream,
- guint pending_send_mask)
-{
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (stream);
- guint flags;
-
-
- /* Don't apply pending send for new streams that haven't been negotiated */
- //if (priv->remote_media == NULL)
- // return;
-
- /* Remember the flags that got changes and then clear the set */
- flags = (priv->pending_send_flags & pending_send_mask);
- priv->pending_send_flags &= ~pending_send_mask;
-
- if (flags != 0)
- {
- if ((flags & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) != 0)
- priv->direction |= TP_MEDIA_STREAM_DIRECTION_SEND;
-
- STREAM_DEBUG (stream, "set direction %u, pending send flags %u", priv->direction, priv->pending_send_flags);
-
- g_signal_emit (stream, signals[SIG_DIRECTION_CHANGED], 0,
- priv->direction, priv->pending_send_flags);
- }
-
- if ((pending_send_mask & TP_MEDIA_STREAM_PENDING_REMOTE_SEND) != 0)
- {
- priv->pending_remote_receive = FALSE;
- STREAM_DEBUG (stream, "remote end ready to receive");
- }
-
- /* Always check to enable sending because the session could become accepted */
- priv_update_sending (stream, priv->direction);
-}
-
-TpMediaStreamDirection
-rakia_media_stream_get_requested_direction (RakiaMediaStream *self)
-{
- return priv_get_requested_direction (RAKIA_MEDIA_STREAM_GET_PRIVATE (self));
-}
-
-/**
- * Returns true if the stream has a valid SDP description and
- * connection has been established with the stream engine.
- */
-gboolean rakia_media_stream_is_local_ready (RakiaMediaStream *self)
-{
- RakiaMediaStreamPrivate *priv = self->priv;
- return (priv->ready_received && priv->native_cands_prepared
- && priv->native_codecs_prepared);
-}
-
-gboolean
-rakia_media_stream_is_codec_intersect_pending (RakiaMediaStream *self)
-{
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (self);
- return priv->codec_intersect_pending;
-}
-
-void
-rakia_media_stream_start_telephony_event (RakiaMediaStream *self, guchar event)
-{
- tp_svc_media_stream_handler_emit_start_telephony_event (
- (TpSvcMediaStreamHandler *)self, event);
-}
-
-void
-rakia_media_stream_stop_telephony_event (RakiaMediaStream *self)
-{
- tp_svc_media_stream_handler_emit_stop_telephony_event (
- (TpSvcMediaStreamHandler *)self);
-}
-
-gboolean
-rakia_media_stream_request_hold_state (RakiaMediaStream *self, gboolean hold)
-{
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (self);
-
- if ((!priv->requested_hold_state) != (!hold))
- {
- priv->requested_hold_state = hold;
- tp_svc_media_stream_handler_emit_set_stream_held (self, hold);
- return TRUE;
- }
- return FALSE;
-}
-
-static void
-priv_emit_local_ready (RakiaMediaStream *self)
-{
- /* Trigger any session updates that are due in the current session state */
- g_signal_emit (self, signals[SIG_LOCAL_MEDIA_UPDATED], 0);
- g_signal_emit (self, signals[SIG_READY], 0);
-}
-
-/**
- * Notify StreamEngine of remote codecs.
- *
- * @pre Ready signal must be receiveid (priv->ready_received)
- */
-static void push_remote_codecs (RakiaMediaStream *stream)
-{
- RakiaMediaStreamPrivate *priv;
- GPtrArray *codecs;
- GType codecs_type;
- GType codec_type;
- GPtrArray *sipcodecs;
- guint i, j;
-
- DEBUG ("enter");
-
- priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (stream);
-
- sipcodecs = rakia_sip_media_get_remote_codecs (priv->media);
- if (sipcodecs == NULL)
- {
- STREAM_DEBUG (stream, "remote media description is not received yet");
- return;
- }
-
- if (!priv->ready_received)
- {
- STREAM_DEBUG (stream, "the stream engine is not ready, SetRemoteCodecs is pending");
- priv->push_remote_codecs_pending = TRUE;
- return;
- }
-
- codec_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CODEC;
- codecs_type = TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CODEC_LIST;
-
- codecs = dbus_g_type_specialized_construct (codecs_type);
-
- for (i = 0; i < sipcodecs->len; i++)
- {
- GValue codec = { 0, };
- GHashTable *opt_params;
- RakiaSipCodec *sipcodec = g_ptr_array_index (sipcodecs, i);
-
- g_value_init (&codec, codec_type);
- g_value_take_boxed (&codec,
- dbus_g_type_specialized_construct (codec_type));
-
- opt_params = g_hash_table_new (g_str_hash, g_str_equal);
- if (sipcodec->params)
- {
- for (j = 0; j < sipcodec->params->len; j++)
- {
- RakiaSipCodecParam *param =
- g_ptr_array_index (sipcodec->params, j);
-
- g_hash_table_insert (opt_params, param->name, param->value);
- }
- }
-
- dbus_g_type_struct_set (&codec,
- /* payload type: */
- 0, sipcodec->id,
- /* encoding name: */
- 1, sipcodec->encoding_name,
- /* media type */
- 2, (guint)priv->media_type,
- /* clock-rate */
- 3, sipcodec->clock_rate,
- /* number of supported channels: */
- 4, sipcodec->channels,
- /* optional params: */
- 5, opt_params,
- G_MAXUINT);
-
- g_hash_table_unref (opt_params);
-
- g_ptr_array_add (codecs, g_value_get_boxed (&codec));
- }
-
-
- STREAM_DEBUG(stream, "emitting %d remote codecs to the handler",
- codecs->len);
-
- tp_svc_media_stream_handler_emit_set_remote_codecs (
- (TpSvcMediaStreamHandler *)stream, codecs);
-
- g_boxed_free (codecs_type, codecs);
-}
-
-static void push_remote_candidates (RakiaMediaStream *stream)
-{
- RakiaMediaStreamPrivate *priv;
- GValue candidate = { 0 };
- GValue transport = { 0 };
- GValue transport_rtcp = { 0 };
- GPtrArray *candidates;
- GPtrArray *transports;
- GType candidate_type;
- GType candidates_type;
- GType transport_type;
- GType transports_type;
- gchar *candidate_id;
- GPtrArray *remote_candidates;
- RakiaSipCandidate *rtp_cand = NULL;
- RakiaSipCandidate *rtcp_cand = NULL;
- guint i;
-
- DEBUG("enter");
-
- priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (stream);
-
- remote_candidates = rakia_sip_media_get_remote_candidates (priv->media);
-
- if (remote_candidates == NULL)
- {
- STREAM_DEBUG (stream, "remote media description is not received yet");
- return;
- }
-
- if (!priv->ready_received)
- {
- STREAM_DEBUG (stream, "the stream engine is not ready, SetRemoteCandidateList is pending");
- priv->push_remote_cands_pending = TRUE;
- return;
- }
-
- for (i = 0; i < remote_candidates->len; i++)
- {
- RakiaSipCandidate *tmpc = g_ptr_array_index (remote_candidates, i);
-
- if (tmpc->component == 1)
- {
- rtp_cand = tmpc;
- }
- else if (tmpc->component == 2)
- {
- rtcp_cand = tmpc;
- }
- }
-
- if (rtp_cand == NULL)
- {
- STREAM_DEBUG (stream, "no rtp candidate");
- priv->push_remote_cands_pending = TRUE;
- return;
- }
-
- transports_type = TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_TRANSPORT_LIST;
- transports = dbus_g_type_specialized_construct (transports_type);
-
- transport_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_TRANSPORT;
- g_value_init (&transport, transport_type);
- g_value_take_boxed (&transport,
- dbus_g_type_specialized_construct (transport_type));
- dbus_g_type_struct_set (&transport,
- 0, 1, /* component number */
- 1, rtp_cand->ip,
- 2, rtp_cand->port,
- 3, TP_MEDIA_STREAM_BASE_PROTO_UDP,
- 4, "RTP",
- 5, "AVP",
- /* 6, 0.0f, */
- 7, TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL,
- /* 8, "", */
- /* 9, "", */
- G_MAXUINT);
-
- STREAM_DEBUG (stream, "remote RTP address=<%s>, port=<%u>", rtp_cand->ip,
- rtp_cand->port);
- g_ptr_array_add (transports, g_value_get_boxed (&transport));
-
- if (rtcp_cand)
- {
- g_value_init (&transport_rtcp, transport_type);
- g_value_take_boxed (&transport_rtcp,
- dbus_g_type_specialized_construct (transport_type));
- dbus_g_type_struct_set (&transport_rtcp,
- 0, 2, /* component number */
- 1, rtcp_cand->ip,
- 2, rtcp_cand->port,
- 3, TP_MEDIA_STREAM_BASE_PROTO_UDP,
- 4, "RTP",
- 5, "AVP",
- /* 6, 0.0f, */
- 7, TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL,
- /* 8, "", */
- /* 9, "", */
- G_MAXUINT);
-
- STREAM_DEBUG (stream, "remote RTCP address=<%s>, port=<%u>",
- rtcp_cand->ip, rtcp_cand->port);
- g_ptr_array_add (transports, g_value_get_boxed (&transport_rtcp));
- }
-
- g_free (priv->remote_candidate_id);
- candidate_id = g_strdup_printf ("L%u", ++priv->remote_candidate_counter);
- priv->remote_candidate_id = candidate_id;
-
- candidate_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CANDIDATE;
- g_value_init (&candidate, candidate_type);
- g_value_take_boxed (&candidate,
- dbus_g_type_specialized_construct (candidate_type));
- dbus_g_type_struct_set (&candidate,
- 0, candidate_id,
- 1, transports,
- G_MAXUINT);
-
- candidates_type = TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CANDIDATE_LIST;
- candidates = dbus_g_type_specialized_construct (candidates_type);
- g_ptr_array_add (candidates, g_value_get_boxed (&candidate));
-
- STREAM_DEBUG (stream, "emitting SetRemoteCandidateList with %s", candidate_id);
-
- tp_svc_media_stream_handler_emit_set_remote_candidate_list (
- (TpSvcMediaStreamHandler *)stream, candidates);
-
- g_boxed_free (candidates_type, candidates);
- g_boxed_free (transports_type, transports);
-}
-
-
-static void
-stream_handler_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcMediaStreamHandlerClass *klass = (TpSvcMediaStreamHandlerClass *)g_iface;
-
-#define IMPLEMENT(x) tp_svc_media_stream_handler_implement_##x (\
- klass, (tp_svc_media_stream_handler_##x##_impl) rakia_media_stream_##x)
- IMPLEMENT(error);
- IMPLEMENT(native_candidates_prepared);
- IMPLEMENT(new_active_candidate_pair);
- IMPLEMENT(new_native_candidate);
- IMPLEMENT(ready);
- IMPLEMENT(set_local_codecs);
- IMPLEMENT(codecs_updated);
- IMPLEMENT(stream_state);
- IMPLEMENT(supported_codecs);
- IMPLEMENT(hold_state);
- IMPLEMENT(unhold_failure);
-#undef IMPLEMENT
-}
-
-RakiaSipMedia *
-rakia_media_stream_get_media (RakiaMediaStream *stream)
-{
- RakiaMediaStreamPrivate *priv = stream->priv;
-
- return priv->media;
-}