diff -r d0f3a028347a -r 59927b2d3b75 telepathygabble/src/gabble-media-channel.c --- a/telepathygabble/src/gabble-media-channel.c Tue Feb 02 01:10:06 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1622 +0,0 @@ -/* - * gabble-media-channel.c - Source for GabbleMediaChannel - * Copyright (C) 2006 Collabora Ltd. - * - * @author Ole Andre Vadla Ravnaas - * - * 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 -#include -#include - - -#include "ansi.h" -#include "debug.h" -#include "gabble-connection.h" -#include "gabble-media-session.h" -#include "gabble-presence.h" -#include "gabble-presence-cache.h" - -#include "telepathy-errors.h" -#include "telepathy-helpers.h" -#include "telepathy-interfaces.h" -#include "tp-channel-iface.h" - -#include "gabble-media-channel.h" -#include "gabble-media-channel-signals-marshal.h" -#include "gabble-media-channel-glue.h" - -#include "gabble-media-session.h" -#include "gabble-media-stream.h" - -#include "media-factory.h" - -#include "gabble_enums.h" - -#define DEBUG_FLAG GABBLE_DEBUG_MEDIA - -#define TP_SESSION_HANDLER_SET_TYPE (dbus_g_type_get_struct ("GValueArray", \ - DBUS_TYPE_G_OBJECT_PATH, \ - G_TYPE_STRING, \ - G_TYPE_INVALID)) - -#define TP_CHANNEL_STREAM_TYPE (dbus_g_type_get_struct ("GValueArray", \ - G_TYPE_UINT, \ - G_TYPE_UINT, \ - G_TYPE_UINT, \ - G_TYPE_UINT, \ - G_TYPE_UINT, \ - G_TYPE_UINT, \ - G_TYPE_INVALID)) - -#ifndef EMULATOR -G_DEFINE_TYPE_WITH_CODE (GabbleMediaChannel, gabble_media_channel, - G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL)); -#endif - -/* signal enum */ -enum -{ - CLOSED, - NEW_SESSION_HANDLER, - STREAM_ADDED, - STREAM_DIRECTION_CHANGED, - STREAM_ERROR, - STREAM_REMOVED, - STREAM_STATE_CHANGED, - LAST_SIGNAL -#ifdef EMULATOR - = LAST_SIGNAL_MED_CHANNEL -#endif - -}; - - -#ifdef EMULATOR -#include "libgabble_wsd_solution.h" - - GET_STATIC_ARRAY_FROM_TLS(signals,gabble_med_chnl,guint) - #define signals (GET_WSD_VAR_NAME(signals,gabble_med_chnl, s)()) - - GET_STATIC_VAR_FROM_TLS(gabble_media_channel_parent_class,gabble_med_chnl,gpointer) - #define gabble_media_channel_parent_class (*GET_WSD_VAR_NAME(gabble_media_channel_parent_class,gabble_med_chnl,s)()) - - GET_STATIC_VAR_FROM_TLS(g_define_type_id,gabble_med_chnl,GType) - #define g_define_type_id (*GET_WSD_VAR_NAME(g_define_type_id,gabble_med_chnl,s)()) - -static void gabble_media_channel_init (GabbleMediaChannel *self); -static void gabble_media_channel_class_init (GabbleMediaChannelClass *klass); -static void gabble_media_channel_class_intern_init (gpointer klass) - { - gabble_media_channel_parent_class = g_type_class_peek_parent (klass); - gabble_media_channel_class_init ((GabbleMediaChannelClass*) klass); - } - EXPORT_C GType gabble_media_channel_get_type (void) - { - if ((g_define_type_id == 0)) - { static const GTypeInfo g_define_type_info = { sizeof (GabbleMediaChannelClass), (GBaseInitFunc) ((void *)0), (GBaseFinalizeFunc) ((void *)0), (GClassInitFunc) gabble_media_channel_class_intern_init, (GClassFinalizeFunc) ((void *)0), ((void *)0), sizeof (GabbleMediaChannel), 0, (GInstanceInitFunc) gabble_media_channel_init, ((void *)0) }; g_define_type_id = g_type_register_static ( ((GType) ((20) << (2))), g_intern_static_string ("GabbleMediaChannel"), &g_define_type_info, (GTypeFlags) 0); { { static const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc) ((void *)0) }; g_type_add_interface_static (g_define_type_id, tp_channel_iface_get_type(), &g_implement_interface_info); } ; } } return g_define_type_id; - }; - -#else - - static guint signals[LAST_SIGNAL] = {0}; - -#endif - - -/* properties */ -enum -{ - PROP_OBJECT_PATH = 1, - PROP_CHANNEL_TYPE, - PROP_HANDLE_TYPE, - PROP_HANDLE, - PROP_CONNECTION, - PROP_CREATOR, - PROP_FACTORY, - LAST_PROPERTY -}; - -/* private structure */ -typedef struct _GabbleMediaChannelPrivate GabbleMediaChannelPrivate; - -struct _GabbleMediaChannelPrivate -{ - GabbleConnection *conn; - gchar *object_path; - GabbleHandle creator; - - GabbleMediaFactory *factory; - GabbleMediaSession *session; - GPtrArray *streams; - - guint next_stream_id; - - gboolean closed; - gboolean dispose_has_run; -}; - -#define GABBLE_MEDIA_CHANNEL_GET_PRIVATE(obj) \ - ((GabbleMediaChannelPrivate *)obj->priv) - -static void -gabble_media_channel_init (GabbleMediaChannel *self) -{ - GabbleMediaChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - GABBLE_TYPE_MEDIA_CHANNEL, GabbleMediaChannelPrivate); - - self->priv = priv; - - priv->next_stream_id = 1; -} - -static GObject * -gabble_media_channel_constructor (GType type, guint n_props, - GObjectConstructParam *props) -{ - GObject *obj; - GabbleMediaChannelPrivate *priv; - DBusGConnection *bus; - GIntSet *set; - - obj = G_OBJECT_CLASS (gabble_media_channel_parent_class)-> - constructor (type, n_props, props); - - priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (GABBLE_MEDIA_CHANNEL (obj)); - - /* register object on the bus */ - bus = tp_get_bus (); - dbus_g_connection_register_g_object (bus, priv->object_path, obj); - - gabble_group_mixin_init (obj, G_STRUCT_OFFSET (GabbleMediaChannel, group), - priv->conn->handles, priv->conn->self_handle); - - /* automatically add creator to channel */ - set = g_intset_new (); - g_intset_add (set, priv->creator); - - gabble_group_mixin_change_members (obj, "", set, NULL, NULL, NULL, 0, 0); - - g_intset_destroy (set); - - /* allow member adding */ - gabble_group_mixin_change_flags (obj, TP_CHANNEL_GROUP_FLAG_CAN_ADD, 0); - - return obj; -} - -static void session_state_changed_cb (GabbleMediaSession *session, GParamSpec *arg1, GabbleMediaChannel *channel); -static void session_stream_added_cb (GabbleMediaSession *session, GabbleMediaStream *stream, GabbleMediaChannel *chan); -static void session_terminated_cb (GabbleMediaSession *session, guint terminator, guint reason, gpointer user_data); - -/** - * create_session - * - * Creates a GabbleMediaSession object for given peer. - * - * If sid is set to NULL a unique sid is generated and - * the "initiator" property of the newly created - * GabbleMediaSession is set to our own handle. - */ -static GabbleMediaSession* -create_session (GabbleMediaChannel *channel, - GabbleHandle peer, - const gchar *peer_resource, - const gchar *sid) -{ - GabbleMediaChannelPrivate *priv; - GabbleMediaSession *session; - gchar *object_path; - JingleInitiator initiator; - - g_assert (GABBLE_IS_MEDIA_CHANNEL (channel)); - - priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (channel); - - g_assert (priv->session == NULL); - - object_path = g_strdup_printf ("%s/MediaSession%u", priv->object_path, peer); - - if (sid == NULL) - { - initiator = INITIATOR_LOCAL; - sid = _gabble_media_factory_allocate_sid (priv->factory, channel); - } - else - { - initiator = INITIATOR_REMOTE; - _gabble_media_factory_register_sid (priv->factory, sid, channel); - } - - session = g_object_new (GABBLE_TYPE_MEDIA_SESSION, - "connection", priv->conn, - "media-channel", channel, - "object-path", object_path, - "session-id", sid, - "initiator", initiator, - "peer", peer, - "peer-resource", peer_resource, - NULL); - - g_signal_connect (session, "notify::state", - (GCallback) session_state_changed_cb, channel); - g_signal_connect (session, "stream-added", - (GCallback) session_stream_added_cb, channel); - g_signal_connect (session, "terminated", - (GCallback) session_terminated_cb, channel); - - priv->session = session; - - priv->streams = g_ptr_array_sized_new (1); - - g_signal_emit (channel, signals[NEW_SESSION_HANDLER], 0, - object_path, "rtp"); - - g_free (object_path); - - return session; -} - -gboolean -_gabble_media_channel_dispatch_session_action (GabbleMediaChannel *chan, - GabbleHandle peer, - const gchar *peer_resource, - const gchar *sid, - LmMessage *message, - LmMessageNode *session_node, - const gchar *action, - GError **error) -{ - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan); - GabbleMediaSession *session = priv->session; - gboolean session_is_new = FALSE; - - if (session == NULL) - { - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (chan); - GIntSet *set; - - session = create_session (chan, peer, peer_resource, sid); - session_is_new = TRUE; - - /* make us local pending */ - set = g_intset_new (); - g_intset_add (set, mixin->self_handle); - - gabble_group_mixin_change_members (G_OBJECT (chan), "", NULL, NULL, set, - NULL, 0, 0); - - g_intset_destroy (set); - - /* and update flags accordingly */ - gabble_group_mixin_change_flags (G_OBJECT (chan), - TP_CHANNEL_GROUP_FLAG_CAN_ADD | - TP_CHANNEL_GROUP_FLAG_CAN_REMOVE, - 0); - } - - g_object_ref (session); - - if (_gabble_media_session_handle_action (session, message, session_node, - action, error)) - { - g_object_unref (session); - return TRUE; - } - else - { - if (session_is_new) - _gabble_media_session_terminate (session, INITIATOR_LOCAL, - TP_CHANNEL_GROUP_CHANGE_REASON_ERROR); - - g_object_unref (session); - return FALSE; - } -} - -static void -gabble_media_channel_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (object); - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan); - - switch (property_id) { - case PROP_OBJECT_PATH: - g_value_set_string (value, priv->object_path); - break; - case PROP_CHANNEL_TYPE: - g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA); - break; - case PROP_HANDLE_TYPE: - g_value_set_uint (value, TP_HANDLE_TYPE_NONE); - break; - case PROP_HANDLE: - g_value_set_uint (value, 0); - break; - case PROP_CONNECTION: - g_value_set_object (value, priv->conn); - break; - case PROP_CREATOR: - g_value_set_uint (value, priv->creator); - break; - case PROP_FACTORY: - g_value_set_object (value, priv->factory); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gabble_media_channel_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (object); - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan); - - switch (property_id) { - case PROP_OBJECT_PATH: - g_free (priv->object_path); - priv->object_path = g_value_dup_string (value); - break; - case PROP_HANDLE: - /* this property is writable in the interface, but not actually - * meaningfully changable on this channel, so we do nothing */ - break; - case PROP_CONNECTION: - priv->conn = g_value_get_object (value); - break; - case PROP_CREATOR: - priv->creator = g_value_get_uint (value); - break; - case PROP_FACTORY: - priv->factory = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void gabble_media_channel_dispose (GObject *object); -static void gabble_media_channel_finalize (GObject *object); -static gboolean gabble_media_channel_remove_member (GObject *obj, GabbleHandle handle, const gchar *message, GError **error); - -static void -gabble_media_channel_class_init (GabbleMediaChannelClass *gabble_media_channel_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (gabble_media_channel_class); - GParamSpec *param_spec; - - g_type_class_add_private (gabble_media_channel_class, sizeof (GabbleMediaChannelPrivate)); - - object_class->constructor = gabble_media_channel_constructor; - - object_class->get_property = gabble_media_channel_get_property; - object_class->set_property = gabble_media_channel_set_property; - - object_class->dispose = gabble_media_channel_dispose; - object_class->finalize = gabble_media_channel_finalize; - - gabble_group_mixin_class_init (object_class, - G_STRUCT_OFFSET (GabbleMediaChannelClass, group_class), - _gabble_media_channel_add_member, - gabble_media_channel_remove_member); - - g_object_class_override_property (object_class, PROP_OBJECT_PATH, "object-path"); - g_object_class_override_property (object_class, PROP_CHANNEL_TYPE, "channel-type"); - g_object_class_override_property (object_class, PROP_HANDLE_TYPE, "handle-type"); - g_object_class_override_property (object_class, PROP_HANDLE, "handle"); - - param_spec = g_param_spec_object ("connection", "GabbleConnection object", - "Gabble connection object that owns this " - "media channel object.", - GABBLE_TYPE_CONNECTION, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); - g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); - - param_spec = g_param_spec_uint ("creator", "Channel creator", - "The GabbleHandle representing the contact " - "who created the channel.", - 0, G_MAXUINT32, 0, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_BLURB); - g_object_class_install_property (object_class, PROP_CREATOR, param_spec); - - param_spec = g_param_spec_object ("factory", "GabbleMediaFactory object", - "The factory that created this object.", - GABBLE_TYPE_MEDIA_FACTORY, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); - g_object_class_install_property (object_class, PROP_FACTORY, param_spec); - - signals[CLOSED] = - g_signal_new ("closed", - G_OBJECT_CLASS_TYPE (gabble_media_channel_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[NEW_SESSION_HANDLER] = - g_signal_new ("new-session-handler", - G_OBJECT_CLASS_TYPE (gabble_media_channel_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, - 0, - NULL, NULL, - gabble_media_channel_marshal_VOID__STRING_STRING, - G_TYPE_NONE, 2, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_STRING); - - signals[STREAM_ADDED] = - g_signal_new ("stream-added", - G_OBJECT_CLASS_TYPE (gabble_media_channel_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, - 0, - NULL, NULL, - gabble_media_channel_marshal_VOID__UINT_UINT_UINT, - G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); - - signals[STREAM_DIRECTION_CHANGED] = - g_signal_new ("stream-direction-changed", - G_OBJECT_CLASS_TYPE (gabble_media_channel_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, - 0, - NULL, NULL, - gabble_media_channel_marshal_VOID__UINT_UINT_UINT, - G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); - - signals[STREAM_ERROR] = - g_signal_new ("stream-error", - G_OBJECT_CLASS_TYPE (gabble_media_channel_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, - 0, - NULL, NULL, - gabble_media_channel_marshal_VOID__UINT_UINT_STRING, - G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING); - - signals[STREAM_REMOVED] = - g_signal_new ("stream-removed", - G_OBJECT_CLASS_TYPE (gabble_media_channel_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - - signals[STREAM_STATE_CHANGED] = - g_signal_new ("stream-state-changed", - G_OBJECT_CLASS_TYPE (gabble_media_channel_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, - 0, - NULL, NULL, - gabble_media_channel_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (gabble_media_channel_class), &dbus_glib_gabble_media_channel_object_info); -} - -void -gabble_media_channel_dispose (GObject *object) -{ - GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (object); - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self); - - if (priv->dispose_has_run) - return; - - priv->dispose_has_run = TRUE; - - /** In this we set the state to ENDED, then the callback unrefs - * the session - */ - - if (!priv->closed) - gabble_media_channel_close (self, NULL); - - g_assert (priv->closed); - g_assert (priv->session == NULL); - g_assert (priv->streams == NULL); - - if (G_OBJECT_CLASS (gabble_media_channel_parent_class)->dispose) - G_OBJECT_CLASS (gabble_media_channel_parent_class)->dispose (object); -} - -void -gabble_media_channel_finalize (GObject *object) -{ - GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (object); - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self); - - g_free (priv->object_path); - - gabble_group_mixin_finalize (object); - - G_OBJECT_CLASS (gabble_media_channel_parent_class)->finalize (object); -} - - - -/** - * gabble_media_channel_add_members - * - * Implements D-Bus method AddMembers - * on interface org.freedesktop.Telepathy.Channel.Interface.Group - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_add_members (GabbleMediaChannel *self, - const GArray *contacts, - const gchar *message, - GError **error) -{ - return gabble_group_mixin_add_members (G_OBJECT (self), contacts, message, - error); -} - - -/** - * gabble_media_channel_close - * - * Implements D-Bus method Close - * on interface org.freedesktop.Telepathy.Channel - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_close (GabbleMediaChannel *self, - GError **error) -{ - GabbleMediaChannelPrivate *priv; - - gabble_debug (DEBUG_FLAG, "called on %p", self); - - g_assert (GABBLE_IS_MEDIA_CHANNEL (self)); - - priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self); - - if (priv->closed) - return TRUE; - - priv->closed = TRUE; - - if (priv->session) - { - _gabble_media_session_terminate (priv->session, INITIATOR_LOCAL, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); - } - - g_signal_emit (self, signals[CLOSED], 0); - - return TRUE; -} - - -/** - * gabble_media_channel_get_all_members - * - * Implements D-Bus method GetAllMembers - * on interface org.freedesktop.Telepathy.Channel.Interface.Group - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_get_all_members (GabbleMediaChannel *self, - GArray **ret, - GArray **ret1, - GArray **ret2, - GError **error) -{ - return gabble_group_mixin_get_all_members (G_OBJECT (self), ret, ret1, ret2, - error); -} - - -/** - * gabble_media_channel_get_channel_type - * - * Implements D-Bus method GetChannelType - * on interface org.freedesktop.Telepathy.Channel - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_get_channel_type (GabbleMediaChannel *self, - gchar **ret, - GError **error) -{ - *ret = g_strdup (TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA); - - return TRUE; -} - - -/** - * gabble_media_channel_get_group_flags - * - * Implements D-Bus method GetGroupFlags - * on interface org.freedesktop.Telepathy.Channel.Interface.Group - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_get_group_flags (GabbleMediaChannel *self, - guint *ret, - GError **error) -{ - return gabble_group_mixin_get_group_flags (G_OBJECT (self), ret, error); -} - - -/** - * gabble_media_channel_get_handle - * - * Implements D-Bus method GetHandle - * on interface org.freedesktop.Telepathy.Channel - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_get_handle (GabbleMediaChannel *self, - guint *ret, - guint *ret1, - GError **error) -{ - GabbleMediaChannelPrivate *priv; - - g_assert (GABBLE_IS_MEDIA_CHANNEL (self)); - - priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self); - - *ret = 0; - *ret1 = 0; - - return TRUE; -} - - -/** - * gabble_media_channel_get_handle_owners - * - * Implements D-Bus method GetHandleOwners - * on interface org.freedesktop.Telepathy.Channel.Interface.Group - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_get_handle_owners (GabbleMediaChannel *self, - const GArray *handles, - GArray **ret, - GError **error) -{ - return gabble_group_mixin_get_handle_owners (G_OBJECT (self), handles, ret, - error); -} - - -/** - * gabble_media_channel_get_interfaces - * - * Implements D-Bus method GetInterfaces - * on interface org.freedesktop.Telepathy.Channel - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_get_interfaces (GabbleMediaChannel *self, - gchar ***ret, - GError **error) -{ - const gchar *interfaces[] = { - TP_IFACE_CHANNEL_INTERFACE_GROUP, - TP_IFACE_CHANNEL_INTERFACE_MEDIA_SIGNALLING, - NULL - }; - - *ret = g_strdupv ((gchar **) interfaces); - - return TRUE; -} - - -/** - * gabble_media_channel_get_local_pending_members - * - * Implements D-Bus method GetLocalPendingMembers - * on interface org.freedesktop.Telepathy.Channel.Interface.Group - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_get_local_pending_members (GabbleMediaChannel *self, - GArray **ret, - GError **error) -{ - return gabble_group_mixin_get_local_pending_members (G_OBJECT (self), ret, - error); -} - - -/** - * gabble_media_channel_get_members - * - * Implements D-Bus method GetMembers - * on interface org.freedesktop.Telepathy.Channel.Interface.Group - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_get_members (GabbleMediaChannel *self, - GArray **ret, - GError **error) -{ - return gabble_group_mixin_get_members (G_OBJECT (self), ret, error); -} - - -/** - * gabble_media_channel_get_remote_pending_members - * - * Implements D-Bus method GetRemotePendingMembers - * on interface org.freedesktop.Telepathy.Channel.Interface.Group - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_get_remote_pending_members (GabbleMediaChannel *self, - GArray **ret, - GError **error) -{ - return gabble_group_mixin_get_remote_pending_members (G_OBJECT (self), ret, - error); -} - - -/** - * gabble_media_channel_get_self_handle - * - * Implements D-Bus method GetSelfHandle - * on interface org.freedesktop.Telepathy.Channel.Interface.Group - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_get_self_handle (GabbleMediaChannel *self, - guint *ret, - GError **error) -{ - return gabble_group_mixin_get_self_handle (G_OBJECT (self), ret, error); -} - - -/** - * gabble_media_channel_get_session_handlers - * - * Implements D-Bus method GetSessionHandlers - * on interface org.freedesktop.Telepathy.Channel.Interface.MediaSignalling - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_get_session_handlers (GabbleMediaChannel *self, - GPtrArray **ret, - GError **error) -{ - GabbleMediaChannelPrivate *priv; - - g_assert (GABBLE_IS_MEDIA_CHANNEL (self)); - - priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self); - - if (priv->session) - { - GValue handler = { 0, }; - GabbleHandle member; - gchar *path; - - g_value_init (&handler, TP_SESSION_HANDLER_SET_TYPE); - g_value_take_boxed (&handler, - dbus_g_type_specialized_construct (TP_SESSION_HANDLER_SET_TYPE)); - - g_object_get (priv->session, - "peer", &member, - "object-path", &path, - NULL); - - dbus_g_type_struct_set (&handler, - 0, path, - 1, "rtp", - G_MAXUINT); - - g_free (path); - - *ret = g_ptr_array_sized_new (1); - g_ptr_array_add (*ret, g_value_get_boxed (&handler)); - } - else - { - *ret = g_ptr_array_sized_new (0); - } - - return TRUE; -} - - -static GPtrArray * -make_stream_list (GabbleMediaChannel *self, - GPtrArray *streams) -{ - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self); - GPtrArray *ret; - guint i; - - ret = g_ptr_array_sized_new (streams->len); - - for (i = 0; i < streams->len; i++) - { - GabbleMediaStream *stream = g_ptr_array_index (streams, i); - GValue entry = { 0, }; - guint id; - GabbleHandle peer; - TpCodecMediaType type; - TpMediaStreamState connection_state; - CombinedStreamDirection combined_direction; - - g_object_get (stream, - "id", &id, - "media-type", &type, - "connection-state", &connection_state, - "combined-direction", &combined_direction, - NULL); - - g_object_get (priv->session, "peer", &peer, NULL); - - g_value_init (&entry, TP_CHANNEL_STREAM_TYPE); - g_value_take_boxed (&entry, - dbus_g_type_specialized_construct (TP_CHANNEL_STREAM_TYPE)); - - dbus_g_type_struct_set (&entry, - 0, id, - 1, peer, - 2, type, - 3, connection_state, - 4, COMBINED_DIRECTION_GET_DIRECTION (combined_direction), - 5, COMBINED_DIRECTION_GET_PENDING_SEND (combined_direction), - G_MAXUINT); - - g_ptr_array_add (ret, g_value_get_boxed (&entry)); - } - - return ret; -} - -/** - * gabble_media_channel_list_streams - * - * Implements D-Bus method ListStreams - * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_list_streams (GabbleMediaChannel *self, - GPtrArray **ret, - GError **error) -{ - GabbleMediaChannelPrivate *priv; - - g_assert (GABBLE_IS_MEDIA_CHANNEL (self)); - - priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self); - - /* no session yet? return an empty array */ - if (priv->session == NULL) - { - *ret = g_ptr_array_new (); - - return TRUE; - } - - *ret = make_stream_list (self, priv->streams); - - return TRUE; -} - - -/** - * gabble_media_channel_remove_members - * - * Implements D-Bus method RemoveMembers - * on interface org.freedesktop.Telepathy.Channel.Interface.Group - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_remove_members (GabbleMediaChannel *self, - const GArray *contacts, - const gchar *message, - GError **error) -{ - return gabble_group_mixin_remove_members (G_OBJECT (self), contacts, message, - error); -} - - -static GabbleMediaStream * -_find_stream_by_id (GabbleMediaChannel *chan, guint stream_id) -{ - GabbleMediaChannelPrivate *priv; - guint i; - - g_assert (GABBLE_IS_MEDIA_CHANNEL (chan)); - - priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan); - - for (i = 0; i < priv->streams->len; i++) - { - GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i); - guint id; - - g_object_get (stream, "id", &id, NULL); - if (id == stream_id) - return stream; - } - - return NULL; -} - -/** - * gabble_media_channel_remove_streams - * - * Implements DBus method RemoveStreams - * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia - * - * @error: Used to return a pointer to a GError detailing any error - * that occured, DBus will throw the error only if this - * function returns false. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean gabble_media_channel_remove_streams (GabbleMediaChannel *obj, const GArray * streams, GError **error) -{ - GabbleMediaChannelPrivate *priv; - GPtrArray *stream_objs; - guint i; - - g_assert (GABBLE_IS_MEDIA_CHANNEL (obj)); - - priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (obj); - - *error = NULL; - - stream_objs = g_ptr_array_sized_new (streams->len); - - /* check that all stream ids are valid and at the same time build an array - * of stream objects so we don't have to look them up again after verifying - * all stream identifiers. */ - for (i = 0; i < streams->len; i++) - { - guint id = g_array_index (streams, guint, i); - GabbleMediaStream *stream; - guint j; - - stream = _find_stream_by_id (obj, id); - if (stream == NULL) - { - g_set_error (error, TELEPATHY_ERRORS, InvalidArgument, - "given stream id %u does not exist", id); - goto OUT; - } - - /* make sure we don't allow the client to repeatedly remove the same stream */ - for (j = 0; j < stream_objs->len; j++) - { - GabbleMediaStream *tmp = g_ptr_array_index (stream_objs, j); - - if (tmp == stream) - { - stream = NULL; - break; - } - } - - if (stream != NULL) - g_ptr_array_add (stream_objs, stream); - } - - /* groovy, it's all good dude, let's remove them */ - if (stream_objs->len > 0) - _gabble_media_session_remove_streams (priv->session, (GabbleMediaStream **) - stream_objs->pdata, stream_objs->len); - -OUT: - g_ptr_array_free (stream_objs, TRUE); - - return (*error == NULL); -} - - -/** - * gabble_media_channel_request_stream_direction - * - * Implements D-Bus method RequestStreamDirection - * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_request_stream_direction (GabbleMediaChannel *self, - guint stream_id, - guint stream_direction, - GError **error) -{ - GabbleMediaChannelPrivate *priv; - GabbleMediaStream *stream; - - g_assert (GABBLE_IS_MEDIA_CHANNEL (self)); - - priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self); - - if (stream_direction > TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL) - { - g_set_error (error, TELEPATHY_ERRORS, InvalidArgument, - "given stream direction %u is not valid", stream_direction); - return FALSE; - } - - stream = _find_stream_by_id (self, stream_id); - if (stream == NULL) - { - g_set_error (error, TELEPATHY_ERRORS, InvalidArgument, - "given stream id %u does not exist", stream_id); - return FALSE; - } - - /* streams with no session? I think not... */ - g_assert (priv->session != NULL); - - return _gabble_media_session_request_stream_direction (priv->session, stream, - stream_direction, error); -} - - -/** - * gabble_media_channel_request_streams - * - * Implements D-Bus method RequestStreams - * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia - * - * @error: Used to return a pointer to a GError detailing any error - * that occurred, D-Bus will throw the error only if this - * function returns FALSE. - * - * Returns: TRUE if successful, FALSE if an error was thrown. - */ -gboolean -gabble_media_channel_request_streams (GabbleMediaChannel *self, - guint contact_handle, - const GArray *types, - GPtrArray **ret, - GError **error) -{ - GabbleMediaChannelPrivate *priv; - GPtrArray *streams; - - g_assert (GABBLE_IS_MEDIA_CHANNEL (self)); - - priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (self); - - if (!gabble_handle_is_valid (priv->conn->handles, TP_HANDLE_TYPE_CONTACT, - contact_handle, error)) - return FALSE; - - if (!handle_set_is_member (self->group.members, contact_handle) && - !handle_set_is_member (self->group.remote_pending, contact_handle)) - { - g_set_error (error, TELEPATHY_ERRORS, InvalidArgument, - "given handle %u is not a member of the channel", contact_handle); - return FALSE; - } - - /* if the person is a channel member, we should have a session */ - g_assert (priv->session != NULL); - - if (!_gabble_media_session_request_streams (priv->session, types, &streams, - error)) - return FALSE; - - *ret = make_stream_list (self, streams); - - g_ptr_array_free (streams, TRUE); - - return TRUE; -} - - -gboolean -_gabble_media_channel_add_member (GObject *obj, GabbleHandle handle, const gchar *message, GError **error) -{ - GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (obj); - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan); - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - - /* did we create this channel? */ - if (priv->creator == mixin->self_handle) - { - GabblePresence *presence; - GIntSet *set; - - /* yes: check the peer's capabilities */ - - presence = gabble_presence_cache_get (priv->conn->presence_cache, handle); - - if (presence == NULL || - !(presence->caps & PRESENCE_CAP_GOOGLE_VOICE || - presence->caps & PRESENCE_CAP_JINGLE_DESCRIPTION_AUDIO || - presence->caps & PRESENCE_CAP_JINGLE_DESCRIPTION_VIDEO)) - { - if (presence == NULL) - gabble_debug (DEBUG_FLAG, "failed to add contact %d (%s) to media channel: " - "no presence available", handle, - gabble_handle_inspect (priv->conn->handles, - TP_HANDLE_TYPE_CONTACT, handle)); - else - gabble_debug (DEBUG_FLAG, "failed to add contact %d (%s) to media channel: " - "caps %x aren't sufficient", handle, - gabble_handle_inspect (priv->conn->handles, - TP_HANDLE_TYPE_CONTACT, handle), - presence->caps); - - g_set_error (error, TELEPATHY_ERRORS, NotAvailable, - "handle %u has no media capabilities", handle); - return FALSE; - } - - /* yes: invite the peer */ - - - /* create a new session */ - create_session (chan, handle, NULL, NULL); - - /* make the peer remote pending */ - set = g_intset_new (); - g_intset_add (set, handle); - - gabble_group_mixin_change_members (obj, "", NULL, NULL, NULL, set, 0, 0); - - g_intset_destroy (set); - - /* and update flags accordingly */ - gabble_group_mixin_change_flags (obj, - TP_CHANNEL_GROUP_FLAG_CAN_REMOVE | - TP_CHANNEL_GROUP_FLAG_CAN_RESCIND, - TP_CHANNEL_GROUP_FLAG_CAN_ADD); - - return TRUE; - } - else - { - /* no: has a session been created, is the handle being added ours, - * and are we in local pending? */ - - if (priv->session && - handle == mixin->self_handle && - handle_set_is_member (mixin->local_pending, handle)) - { - /* yes: accept the request */ - - GIntSet *set; - - /* make us a member */ - set = g_intset_new (); - g_intset_add (set, handle); - - gabble_group_mixin_change_members (obj, "", set, NULL, NULL, NULL, 0, 0); - - g_intset_destroy (set); - - /* update flags */ - gabble_group_mixin_change_flags (obj, 0, TP_CHANNEL_GROUP_FLAG_CAN_ADD); - - /* signal acceptance */ - _gabble_media_session_accept (priv->session); - - return TRUE; - } - } - - g_set_error (error, TELEPATHY_ERRORS, NotAvailable, - "handle %u cannot be added in the current state", handle); - return FALSE; -} - -static gboolean -gabble_media_channel_remove_member (GObject *obj, GabbleHandle handle, const gchar *message, GError **error) -{ - GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (obj); - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan); - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (obj); - GIntSet *set; - - if (priv->session == NULL) - { - g_set_error (error, TELEPATHY_ERRORS, NotAvailable, - "handle %u cannot be removed in the current state", handle); - - return FALSE; - } - - if (priv->creator != mixin->self_handle && - handle != mixin->self_handle) - { - g_set_error (error, TELEPATHY_ERRORS, PermissionDenied, - "handle %u cannot be removed because you are not the creator of the" - " channel", handle); - - return FALSE; - } - - _gabble_media_session_terminate (priv->session, INITIATOR_LOCAL, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); - - /* remove the member */ - set = g_intset_new (); - g_intset_add (set, handle); - - gabble_group_mixin_change_members (obj, "", NULL, set, NULL, NULL, 0, 0); - - g_intset_destroy (set); - - /* and update flags accordingly */ - gabble_group_mixin_change_flags (obj, TP_CHANNEL_GROUP_FLAG_CAN_ADD, - TP_CHANNEL_GROUP_FLAG_CAN_REMOVE | - TP_CHANNEL_GROUP_FLAG_CAN_RESCIND); - - return TRUE; -} - -static void -session_terminated_cb (GabbleMediaSession *session, - guint terminator, - guint reason, - gpointer user_data) -{ - GabbleMediaChannel *channel = (GabbleMediaChannel *) user_data; - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (channel); - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (channel); - GError *error = NULL; - gchar *sid; - JingleSessionState state; - GabbleHandle peer; - GIntSet *set; - - g_object_get (session, - "state", &state, - "peer", &peer, - NULL); - - set = g_intset_new (); - - /* remove us and the peer from the member list */ - g_intset_add (set, mixin->self_handle); - g_intset_add (set, peer); - - gabble_group_mixin_change_members (G_OBJECT (channel), "", NULL, set, NULL, NULL, terminator, reason); - - /* update flags accordingly -- allow adding, deny removal */ - gabble_group_mixin_change_flags (G_OBJECT (channel), TP_CHANNEL_GROUP_FLAG_CAN_ADD, - TP_CHANNEL_GROUP_FLAG_CAN_REMOVE); - - /* free the session ID */ - g_object_get (priv->session, "session-id", &sid, NULL); - _gabble_media_factory_free_sid (priv->factory, sid); - g_free (sid); - - /* unref streams */ - if (priv->streams != NULL) - { - GPtrArray *tmp = priv->streams; - - /* move priv->streams aside so that the stream_close_cb - * doesn't double unref */ - priv->streams = NULL; - g_ptr_array_foreach (tmp, (GFunc) g_object_unref, NULL); - g_ptr_array_free (tmp, TRUE); - } - - /* remove the session */ - g_object_unref (priv->session); - priv->session = NULL; - - /* close the channel */ - if (!gabble_media_channel_close (channel, &error)) - { - g_warning ("%s: failed to close media channel: %s", G_STRFUNC, - error->message); - } -} - - -static void -session_state_changed_cb (GabbleMediaSession *session, - GParamSpec *arg1, - GabbleMediaChannel *channel) -{ - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (channel); - GabbleGroupMixin *mixin = GABBLE_GROUP_MIXIN (channel); - JingleSessionState state; - GabbleHandle peer; - GIntSet *set; - - g_object_get (session, - "state", &state, - "peer", &peer, - NULL); - - if (state != JS_STATE_ACTIVE) - return; - - if (priv->creator != mixin->self_handle) - return; - - set = g_intset_new (); - - /* add the peer to the member list */ - g_intset_add (set, peer); - - gabble_group_mixin_change_members (G_OBJECT (channel), "", set, NULL, NULL, NULL, 0, 0); - - /* update flags accordingly -- allow removal, deny adding and rescinding */ - gabble_group_mixin_change_flags (G_OBJECT (channel), - TP_CHANNEL_GROUP_FLAG_CAN_REMOVE, - TP_CHANNEL_GROUP_FLAG_CAN_ADD | - TP_CHANNEL_GROUP_FLAG_CAN_RESCIND); - - g_intset_destroy (set); -} - -static void -stream_close_cb (GabbleMediaStream *stream, - GabbleMediaChannel *chan) -{ - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan); - guint id; - - g_object_get (stream, "id", &id, NULL); - - g_signal_emit (chan, signals[STREAM_REMOVED], 0, id); - - if (priv->streams != NULL) - { - g_ptr_array_remove (priv->streams, stream); - g_object_unref (stream); - } -} - -static void -stream_error_cb (GabbleMediaStream *stream, - TpMediaStreamError errno, - const gchar *message, - GabbleMediaChannel *chan) -{ - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan); - guint id; - - /* emit signal */ - g_object_get (stream, "id", &id, NULL); - g_signal_emit (chan, signals[STREAM_ERROR], 0, id, errno, message); - - /* remove stream from session */ - _gabble_media_session_remove_streams (priv->session, &stream, 1); -} - -static void -stream_state_changed_cb (GabbleMediaStream *stream, - GParamSpec *pspec, - GabbleMediaChannel *chan) -{ - guint id; - TpMediaStreamState connection_state; - - g_object_get (stream, "id", &id, "connection-state", &connection_state, NULL); - - g_signal_emit (chan, signals[STREAM_STATE_CHANGED], 0, id, connection_state); -} - -static void -stream_direction_changed_cb (GabbleMediaStream *stream, - GParamSpec *pspec, - GabbleMediaChannel *chan) -{ - guint id; - CombinedStreamDirection combined; - TpMediaStreamDirection direction; - TpMediaStreamPendingSend pending_send; - - g_object_get (stream, - "id", &id, - "combined-direction", &combined, - NULL); - - direction = COMBINED_DIRECTION_GET_DIRECTION (combined); - pending_send = COMBINED_DIRECTION_GET_PENDING_SEND (combined); - - g_signal_emit (chan, signals[STREAM_DIRECTION_CHANGED], 0, id, direction, - pending_send); -} - -static void -session_stream_added_cb (GabbleMediaSession *session, - GabbleMediaStream *stream, - GabbleMediaChannel *chan) -{ - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan); - - guint id, handle, type; - - /* keep track of the stream */ - g_object_ref (stream); - g_ptr_array_add (priv->streams, stream); - - g_signal_connect (stream, "close", - (GCallback) stream_close_cb, chan); - g_signal_connect (stream, "error", - (GCallback) stream_error_cb, chan); - g_signal_connect (stream, "notify::connection-state", - (GCallback) stream_state_changed_cb, chan); - g_signal_connect (stream, "notify::combined-direction", - (GCallback) stream_direction_changed_cb, chan); - - /* emit StreamAdded */ - g_object_get (session, "peer", &handle, NULL); - g_object_get (stream, "id", &id, "media-type", &type, NULL); - - g_signal_emit (chan, signals[STREAM_ADDED], 0, id, handle, type); -} - -guint -_gabble_media_channel_get_stream_id (GabbleMediaChannel *chan) -{ - GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan); - - return priv->next_stream_id++; -} - -#define AUDIO_CAPS \ - ( PRESENCE_CAP_GOOGLE_VOICE | PRESENCE_CAP_JINGLE_DESCRIPTION_AUDIO ) - -#define VIDEO_CAPS \ - ( PRESENCE_CAP_JINGLE_DESCRIPTION_VIDEO ) - -GabblePresenceCapabilities -_gabble_media_channel_typeflags_to_caps (TpChannelMediaCapabilities flags) -{ - GabblePresenceCapabilities caps = 0; - - if (flags & TP_CHANNEL_MEDIA_CAPABILITY_AUDIO) - caps |= AUDIO_CAPS; - - if (flags & TP_CHANNEL_MEDIA_CAPABILITY_VIDEO) - caps |= VIDEO_CAPS; - - return caps; -} - -TpChannelMediaCapabilities -_gabble_media_channel_caps_to_typeflags (GabblePresenceCapabilities caps) -{ - TpChannelMediaCapabilities typeflags = 0; - - if (caps & AUDIO_CAPS) - typeflags |= TP_CHANNEL_MEDIA_CAPABILITY_AUDIO; - - if (caps & VIDEO_CAPS) - typeflags |= TP_CHANNEL_MEDIA_CAPABILITY_VIDEO; - - return typeflags; -} - -//Added to avoid type casting error in winscw -GabblePresenceCapabilities -_gabble_media_channel_typeflags_to_caps_tmp (guint flags) -{ -return _gabble_media_channel_typeflags_to_caps( (TpChannelMediaCapabilities) flags); -} - -//Added to avoid type casting error in winscw -guint -_gabble_media_channel_caps_to_typeflags_tmp (GabblePresenceCapabilities caps) -{ -return (guint) _gabble_media_channel_caps_to_typeflags(caps); -} -