]> git.0d.be Git - empathy.git/commitdiff
EmpathyTpCall -> EmpathyTpStreamedMedia
authorEmilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>
Thu, 3 Feb 2011 12:15:12 +0000 (12:15 +0000)
committerEmilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>
Thu, 3 Feb 2011 15:00:33 +0000 (15:00 +0000)
libempathy/Makefile.am
libempathy/empathy-call-factory.c
libempathy/empathy-call-handler.c
libempathy/empathy-call-handler.h
libempathy/empathy-tp-call.c [deleted file]
libempathy/empathy-tp-call.h [deleted file]
libempathy/empathy-tp-streamed-media.c [new file with mode: 0644]
libempathy/empathy-tp-streamed-media.h [new file with mode: 0644]
libempathy/empathy-utils.c
src/empathy-call-window.c
src/empathy-event-manager.c

index 25153eab891fca2d5167d6439bd4d8e8afdac2a4..497d8d99b0b3fc60eba82d6b9cd1905f89b2a9b0 100644 (file)
@@ -57,12 +57,12 @@ libempathy_headers =                                \
        empathy-time.h                          \
        empathy-tls-certificate.h               \
        empathy-tls-verifier.h                  \
-       empathy-tp-call.h                       \
        empathy-tp-chat.h                       \
        empathy-tp-contact-factory.h            \
        empathy-tp-contact-list.h               \
        empathy-tp-file.h                       \
        empathy-tp-roomlist.h                   \
+       empathy-tp-streamed-media.h             \
        empathy-types.h                         \
        empathy-utils.h
 
@@ -97,12 +97,12 @@ libempathy_la_SOURCES =                                     \
        empathy-time.c                                  \
        empathy-tls-certificate.c                       \
        empathy-tls-verifier.c                          \
-       empathy-tp-call.c                               \
        empathy-tp-chat.c                               \
        empathy-tp-contact-factory.c                    \
        empathy-tp-contact-list.c                       \
        empathy-tp-file.c                               \
        empathy-tp-roomlist.c                           \
+       empathy-tp-streamed-media.c                     \
        empathy-utils.c
 
 # do not distribute generated files
index 49bc60de9c0c5d6b65f683ecab42256d7ec7aa0b..6e523aada7de29b92281d1e72a13fc1f20674453 100644 (file)
@@ -261,7 +261,7 @@ empathy_call_factory_new_call_with_streams (EmpathyContact *contact,
 
 static void
 create_call_handler (EmpathyCallFactory *factory,
-  EmpathyTpCall *call)
+  EmpathyTpStreamedMedia *call)
 {
   EmpathyCallHandler *handler;
 
@@ -276,11 +276,11 @@ create_call_handler (EmpathyCallFactory *factory,
 }
 
 static void
-call_status_changed_cb (EmpathyTpCall *call,
+call_status_changed_cb (EmpathyTpStreamedMedia *call,
     GParamSpec *spec,
     EmpathyCallFactory *self)
 {
-  if (empathy_tp_call_get_status (call) <= EMPATHY_TP_CALL_STATUS_READYING)
+  if (empathy_tp_streamed_media_get_status (call) <= EMPATHY_TP_STREAMED_MEDIA_STATUS_READYING)
     return;
 
   create_call_handler (self, call);
@@ -305,7 +305,7 @@ handle_channels_cb (TpSimpleHandler *handler,
   for (l = channels; l != NULL; l = g_list_next (l))
     {
       TpChannel *channel = l->data;
-      EmpathyTpCall *call;
+      EmpathyTpStreamedMedia *call;
 
       if (tp_proxy_get_invalidated (channel) != NULL)
         continue;
@@ -314,11 +314,11 @@ handle_channels_cb (TpSimpleHandler *handler,
           TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA)
         continue;
 
-      call = empathy_tp_call_new (account, channel);
+      call = empathy_tp_streamed_media_new (account, channel);
 
-      if (empathy_tp_call_get_status (call) <= EMPATHY_TP_CALL_STATUS_READYING)
+      if (empathy_tp_streamed_media_get_status (call) <= EMPATHY_TP_STREAMED_MEDIA_STATUS_READYING)
         {
-          /* We have to wait that the TpCall is ready as the
+          /* We have to wait that the TpStreamedMedia is ready as the
            * call-handler rely on it. */
           tp_g_signal_connect_object (call, "notify::status",
               G_CALLBACK (call_status_changed_cb), self, 0);
index dc734b2e5337047301260334ede3698433b05c0f..c3ce5fed47a870b5e2f996ec0981d8a9d5de9799 100644 (file)
@@ -54,7 +54,7 @@ enum {
 static guint signals[LAST_SIGNAL] = {0};
 
 enum {
-  PROP_TP_CALL = 1,
+  PROP_TP_STREAMED_MEDIA = 1,
   PROP_GST_BUS,
   PROP_CONTACT,
   PROP_INITIAL_AUDIO,
@@ -73,7 +73,7 @@ enum {
 
 typedef struct {
   gboolean dispose_has_run;
-  EmpathyTpCall *call;
+  EmpathyTpStreamedMedia *call;
   EmpathyContact *contact;
   TfChannel *tfchannel;
   gboolean initial_audio;
@@ -113,7 +113,7 @@ empathy_call_handler_dispose (GObject *object)
 
   if (priv->call != NULL)
     {
-      empathy_tp_call_close (priv->call);
+      empathy_tp_streamed_media_close (priv->call);
       g_object_unref (priv->call);
     }
 
@@ -173,7 +173,7 @@ empathy_call_handler_set_property (GObject *object,
       case PROP_CONTACT:
         priv->contact = g_value_dup_object (value);
         break;
-      case PROP_TP_CALL:
+      case PROP_TP_STREAMED_MEDIA:
         priv->call = g_value_dup_object (value);
         break;
       case PROP_INITIAL_AUDIO:
@@ -198,7 +198,7 @@ empathy_call_handler_get_property (GObject *object,
       case PROP_CONTACT:
         g_value_set_object (value, priv->contact);
         break;
-      case PROP_TP_CALL:
+      case PROP_TP_STREAMED_MEDIA:
         g_value_set_object (value, priv->call);
         break;
       case PROP_INITIAL_AUDIO:
@@ -259,9 +259,9 @@ empathy_call_handler_class_init (EmpathyCallHandlerClass *klass)
 
   param_spec = g_param_spec_object ("tp-call",
     "tp-call", "The calls channel wrapper",
-    EMPATHY_TYPE_TP_CALL,
+    EMPATHY_TYPE_TP_STREAMED_MEDIA,
     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-  g_object_class_install_property (object_class, PROP_TP_CALL, param_spec);
+  g_object_class_install_property (object_class, PROP_TP_STREAMED_MEDIA, param_spec);
 
   param_spec = g_param_spec_boolean ("initial-audio",
     "initial-audio", "Whether the call should start with audio",
@@ -401,11 +401,11 @@ empathy_call_handler_new_for_contact (EmpathyContact *contact)
 }
 
 EmpathyCallHandler *
-empathy_call_handler_new_for_channel (EmpathyTpCall *call)
+empathy_call_handler_new_for_channel (EmpathyTpStreamedMedia *call)
 {
   return EMPATHY_CALL_HANDLER (g_object_new (EMPATHY_TYPE_CALL_HANDLER,
     "tp-call", call,
-    "initial-video", empathy_tp_call_is_receiving_video (call),
+    "initial-video", empathy_tp_streamed_media_is_receiving_video (call),
     NULL));
 }
 
@@ -629,7 +629,7 @@ empathy_call_handler_tf_stream_src_pad_added_cb (TfStream *stream,
 
 static gboolean
 empathy_call_handler_tf_stream_request_resource_cb (TfStream *stream,
-  guint direction, EmpathyTpCall *call)
+  guint direction, EmpathyTpStreamedMedia *call)
 {
   gboolean ret;
   guint media_type;
@@ -776,7 +776,7 @@ empathy_call_handler_request_cb (GObject *source,
 
   account = tp_account_channel_request_get_account (req);
 
-  priv->call = empathy_tp_call_new (account, channel);
+  priv->call = empathy_tp_streamed_media_new (account, channel);
 
   g_object_notify (G_OBJECT (self), "tp-call");
 
@@ -797,12 +797,12 @@ empathy_call_handler_start_call (EmpathyCallHandler *handler,
   if (priv->call != NULL)
     {
       empathy_call_handler_start_tpfs (handler);
-      empathy_tp_call_accept_incoming_call (priv->call);
+      empathy_tp_streamed_media_accept_incoming_call (priv->call);
       return;
     }
 
-  /* No TpCall object (we are redialing). Request a new media channel that
-   * will be used to create a new EmpathyTpCall. */
+  /* No TpStreamedMedia object (we are redialing). Request a new media channel that
+   * will be used to create a new EmpathyTpStreamedMedia. */
   g_assert (priv->contact != NULL);
 
   account = empathy_contact_get_account (priv->contact);
@@ -831,7 +831,7 @@ empathy_call_handler_stop_call (EmpathyCallHandler *handler)
 
   if (priv->call != NULL)
     {
-      empathy_tp_call_leave (priv->call);
+      empathy_tp_streamed_media_leave (priv->call);
       g_object_unref (priv->call);
     }
 
index 9f6fd9e3b33548e354e12ca5c48aa9404904981d..1e0fd71652e4e54c097cd7524cc41110b4a36c13 100644 (file)
@@ -26,7 +26,7 @@
 #include <gst/gst.h>
 #include <gst/farsight/fs-conference-iface.h>
 
-#include <libempathy/empathy-tp-call.h>
+#include <libempathy/empathy-tp-streamed-media.h>
 #include <libempathy/empathy-contact.h>
 
 G_BEGIN_DECLS
@@ -66,7 +66,7 @@ EmpathyCallHandler * empathy_call_handler_new_for_contact (
   EmpathyContact *contact);
 
 EmpathyCallHandler * empathy_call_handler_new_for_channel (
-  EmpathyTpCall *call);
+  EmpathyTpStreamedMedia *call);
 
 void empathy_call_handler_start_call (EmpathyCallHandler *handler,
     gint64 timestamp);
diff --git a/libempathy/empathy-tp-call.c b/libempathy/empathy-tp-call.c
deleted file mode 100644 (file)
index 1a53de6..0000000
+++ /dev/null
@@ -1,855 +0,0 @@
-/*
- * Copyright (C) 2007 Elliot Fairweather
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * 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
- *
- * Authors: Elliot Fairweather <elliot.fairweather@collabora.co.uk>
- *          Xavier Claessens <xclaesse@gmail.com>
- */
-
-#include <string.h>
-
-#include <telepathy-glib/proxy-subclass.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/util.h>
-
-#include "empathy-tp-call.h"
-#include "empathy-tp-contact-factory.h"
-#include "empathy-utils.h"
-#include "empathy-marshal.h"
-
-#define DEBUG_FLAG EMPATHY_DEBUG_VOIP
-#include "empathy-debug.h"
-
-#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpCall)
-typedef struct
-{
-  gboolean dispose_has_run;
-  TpAccount *account;
-  TpChannel *channel;
-  EmpathyContact *contact;
-  gboolean is_incoming;
-  guint status;
-
-  EmpathyTpCallStream *audio;
-  EmpathyTpCallStream *video;
-} EmpathyTpCallPriv;
-
-/* signal enum */
-enum {
-  AUDIO_STREAM_ERROR,
-  VIDEO_STREAM_ERROR,
-  LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-enum
-{
-  PROP_0,
-  PROP_ACCOUNT,
-  PROP_CHANNEL,
-  PROP_CONTACT,
-  PROP_STATUS,
-  PROP_AUDIO_STREAM,
-  PROP_VIDEO_STREAM
-};
-
-G_DEFINE_TYPE (EmpathyTpCall, empathy_tp_call, G_TYPE_OBJECT)
-
-static void
-tp_call_add_stream (EmpathyTpCall *call,
-                    guint stream_id,
-                    guint contact_handle,
-                    guint stream_type,
-                    guint stream_state,
-                    guint stream_direction)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-
-  switch (stream_type)
-    {
-      case TP_MEDIA_STREAM_TYPE_AUDIO:
-        DEBUG ("Audio stream - id: %d, state: %d, direction: %d",
-            stream_id, stream_state, stream_direction);
-        priv->audio->exists = TRUE;
-        priv->audio->id = stream_id;
-        priv->audio->state = stream_state;
-        priv->audio->direction = stream_direction;
-        g_object_notify (G_OBJECT (call), "audio-stream");
-        break;
-      case TP_MEDIA_STREAM_TYPE_VIDEO:
-        DEBUG ("Video stream - id: %d, state: %d, direction: %d",
-            stream_id, stream_state, stream_direction);
-        priv->video->exists = TRUE;
-        priv->video->id = stream_id;
-        priv->video->state = stream_state;
-        priv->video->direction = stream_direction;
-        g_object_notify (G_OBJECT (call), "video-stream");
-        break;
-      default:
-        DEBUG ("Unknown stream type: %d", stream_type);
-    }
-}
-
-static void
-tp_call_stream_added_cb (TpChannel *channel,
-                         guint stream_id,
-                         guint contact_handle,
-                         guint stream_type,
-                         gpointer user_data,
-                         GObject *call)
-{
-  DEBUG ("Stream added - stream id: %d, contact handle: %d, stream type: %d",
-      stream_id, contact_handle, stream_type);
-
-  tp_call_add_stream (EMPATHY_TP_CALL (call), stream_id, contact_handle,
-      stream_type, TP_MEDIA_STREAM_STATE_DISCONNECTED,
-      TP_MEDIA_STREAM_DIRECTION_NONE);
-}
-
-static void
-tp_call_stream_removed_cb (TpChannel *channel,
-                           guint stream_id,
-                           gpointer user_data,
-                           GObject *call)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-
-  DEBUG ("Stream removed - stream id: %d", stream_id);
-
-  if (stream_id == priv->audio->id)
-    {
-      priv->audio->exists = FALSE;
-      g_object_notify (call, "audio-stream");
-    }
-  else if (stream_id == priv->video->id)
-    {
-      priv->video->exists = FALSE;
-      g_object_notify (call, "video-stream");
-    }
-}
-
-static void
-tp_call_stream_state_changed_cb (TpChannel *proxy,
-                                 guint stream_id,
-                                 guint stream_state,
-                                 gpointer user_data,
-                                 GObject *call)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-
-  DEBUG ("Stream state changed - stream id: %d, state state: %d",
-      stream_id, stream_state);
-
-  if (stream_id == priv->audio->id)
-    {
-      priv->audio->state = stream_state;
-      g_object_notify (call, "audio-stream");
-    }
-  else if (stream_id == priv->video->id)
-    {
-      priv->video->state = stream_state;
-      g_object_notify (call, "video-stream");
-    }
-}
-
-static void
-tp_call_stream_direction_changed_cb (TpChannel *channel,
-                                     guint stream_id,
-                                     guint stream_direction,
-                                     guint pending_flags,
-                                     gpointer user_data,
-                                     GObject *call)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-
-  DEBUG ("Stream direction changed - stream: %d, direction: %d",
-      stream_id, stream_direction);
-
-  if (stream_id == priv->audio->id)
-    {
-      priv->audio->direction = stream_direction;
-      g_object_notify (call, "audio-stream");
-    }
-  else if (stream_id == priv->video->id)
-    {
-      priv->video->direction = stream_direction;
-      g_object_notify (call, "video-stream");
-    }
-}
-
-static void
-tp_call_request_streams_cb (TpChannel *channel,
-                            const GPtrArray *streams,
-                            const GError *error,
-                            gpointer user_data,
-                            GObject *call)
-{
-  guint i;
-
-  if (error)
-    {
-      DEBUG ("Error requesting streams: %s", error->message);
-      return;
-    }
-
-  for (i = 0; i < streams->len; i++)
-    {
-      GValueArray *values;
-      guint stream_id;
-      guint contact_handle;
-      guint stream_type;
-      guint stream_state;
-      guint stream_direction;
-
-      values = g_ptr_array_index (streams, i);
-      stream_id = g_value_get_uint (g_value_array_get_nth (values, 0));
-      contact_handle = g_value_get_uint (g_value_array_get_nth (values, 1));
-      stream_type = g_value_get_uint (g_value_array_get_nth (values, 2));
-      stream_state = g_value_get_uint (g_value_array_get_nth (values, 3));
-      stream_direction = g_value_get_uint (g_value_array_get_nth (values, 4));
-
-      tp_call_add_stream (EMPATHY_TP_CALL (call), stream_id, contact_handle,
-          stream_type, stream_state, stream_direction);
-  }
-}
-
-static void
-tp_call_request_streams_for_capabilities (EmpathyTpCall *call,
-                                          EmpathyCapabilities capabilities)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-  GArray *stream_types;
-  guint handle;
-  guint stream_type;
-
-  if (capabilities == EMPATHY_CAPABILITIES_UNKNOWN)
-      capabilities = EMPATHY_CAPABILITIES_AUDIO | EMPATHY_CAPABILITIES_VIDEO;
-
-  DEBUG ("Requesting new stream for capabilities %d",
-      capabilities);
-
-  stream_types = g_array_new (FALSE, FALSE, sizeof (guint));
-  handle = empathy_contact_get_handle (priv->contact);
-
-  if (capabilities & EMPATHY_CAPABILITIES_AUDIO)
-    {
-      stream_type = TP_MEDIA_STREAM_TYPE_AUDIO;
-      g_array_append_val (stream_types, stream_type);
-    }
-  if (capabilities & EMPATHY_CAPABILITIES_VIDEO)
-    {
-      stream_type = TP_MEDIA_STREAM_TYPE_VIDEO;
-      g_array_append_val (stream_types, stream_type);
-    }
-
-  tp_cli_channel_type_streamed_media_call_request_streams (priv->channel, -1,
-      handle, stream_types, tp_call_request_streams_cb, NULL, NULL,
-      G_OBJECT (call));
-
-  g_array_free (stream_types, TRUE);
-}
-
-static void
-tp_call_got_contact_cb (TpConnection            *connection,
-                        EmpathyContact          *contact,
-                        const GError            *error,
-                        gpointer                 user_data,
-                        GObject                 *call)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-
-  if (error)
-    {
-      DEBUG ("Error: %s", error->message);
-      return;
-    }
-
-  priv->contact = g_object_ref (contact);
-
-  if (priv->status < EMPATHY_TP_CALL_STATUS_PENDING)
-    {
-      priv->status = EMPATHY_TP_CALL_STATUS_PENDING;
-      g_object_notify (G_OBJECT (call), "status");
-    }
-
-  g_object_notify (G_OBJECT (call), "contact");
-}
-
-static void
-tp_call_update_status (EmpathyTpCall *call)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-  TpHandle self_handle;
-  const TpIntSet *set;
-  TpIntSetIter iter;
-
-  g_object_ref (call);
-
-  self_handle = tp_channel_group_get_self_handle (priv->channel);
-  set = tp_channel_group_get_members (priv->channel);
-  tp_intset_iter_init (&iter, set);
-  while (tp_intset_iter_next (&iter))
-    {
-      if (priv->status == EMPATHY_TP_CALL_STATUS_PENDING &&
-          ((priv->is_incoming && iter.element == self_handle) ||
-           (!priv->is_incoming && iter.element != self_handle)))
-        {
-          priv->status = EMPATHY_TP_CALL_STATUS_ACCEPTED;
-          g_object_notify (G_OBJECT (call), "status");
-        }
-    }
-
-  g_object_unref (call);
-}
-
-static void
-tp_call_channel_invalidated_cb (TpChannel     *channel,
-                                GQuark         domain,
-                                gint           code,
-                                gchar         *message,
-                                EmpathyTpCall *call)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-
-  DEBUG ("Channel invalidated: %s", message);
-  priv->status = EMPATHY_TP_CALL_STATUS_CLOSED;
-  g_object_notify (G_OBJECT (call), "status");
-}
-
-static void
-tp_call_async_cb (TpProxy *proxy,
-                  const GError *error,
-                  gpointer user_data,
-                  GObject *call)
-{
-  if (error)
-      DEBUG ("Error %s: %s", (gchar *) user_data, error->message);
-}
-
-static void
-tp_call_stream_error_cb (TpChannel *channel,
-    guint stream_id,
-    guint error_code,
-    const gchar *msg,
-    gpointer user_data,
-    GObject *call)
-{
-  EmpathyTpCall *self = EMPATHY_TP_CALL (call);
-  EmpathyTpCallPriv *priv = GET_PRIV (self);
-
-  DEBUG ("Stream error on stream %u: %s (code: %u)", stream_id, msg,
-      error_code);
-
-  if (priv->audio->id == stream_id)
-    {
-      g_signal_emit (call, signals[AUDIO_STREAM_ERROR], 0, error_code, msg);
-    }
-  else if (priv->video->id == stream_id)
-    {
-      g_signal_emit (call, signals[VIDEO_STREAM_ERROR], 0, error_code, msg);
-    }
-  else
-    {
-      DEBUG ("Unknown stream id: %u", stream_id);
-    }
-}
-
-static GObject *
-tp_call_constructor (GType type,
-                     guint n_construct_params,
-                     GObjectConstructParam *construct_params)
-{
-  GObject *object;
-  EmpathyTpCall *call;
-  EmpathyTpCallPriv *priv;
-
-  object = G_OBJECT_CLASS (empathy_tp_call_parent_class)->constructor (type,
-      n_construct_params, construct_params);
-
-  call = EMPATHY_TP_CALL (object);
-  priv = GET_PRIV (call);
-
-  /* Setup streamed media channel */
-  g_signal_connect (priv->channel, "invalidated",
-      G_CALLBACK (tp_call_channel_invalidated_cb), call);
-  tp_cli_channel_type_streamed_media_connect_to_stream_added (priv->channel,
-      tp_call_stream_added_cb, NULL, NULL, G_OBJECT (call), NULL);
-  tp_cli_channel_type_streamed_media_connect_to_stream_removed (priv->channel,
-      tp_call_stream_removed_cb, NULL, NULL, G_OBJECT (call), NULL);
-  tp_cli_channel_type_streamed_media_connect_to_stream_state_changed (priv->channel,
-      tp_call_stream_state_changed_cb, NULL, NULL, G_OBJECT (call), NULL);
-  tp_cli_channel_type_streamed_media_connect_to_stream_direction_changed (priv->channel,
-      tp_call_stream_direction_changed_cb, NULL, NULL, G_OBJECT (call), NULL);
-  tp_cli_channel_type_streamed_media_connect_to_stream_error (priv->channel,
-      tp_call_stream_error_cb, NULL, NULL, G_OBJECT (call), NULL);
-  tp_cli_channel_type_streamed_media_call_list_streams (priv->channel, -1,
-      tp_call_request_streams_cb, NULL, NULL, G_OBJECT (call));
-
-  /* Is the call incoming? */
-  priv->is_incoming = !tp_channel_get_requested (priv->channel);
-
-  /* Get the remote contact */
-  empathy_tp_contact_factory_get_from_handle (
-      tp_channel_borrow_connection (priv->channel),
-      tp_channel_get_handle (priv->channel, NULL), tp_call_got_contact_cb,
-      NULL, NULL, object);
-
-  /* Update status when members changes */
-  tp_call_update_status (call);
-  tp_g_signal_connect_object (priv->channel, "group-members-changed",
-      G_CALLBACK (tp_call_update_status), call, G_CONNECT_SWAPPED);
-
-  return object;
-}
-static void
-tp_call_dispose (GObject *object)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (object);
-
-  DEBUG ("Disposing: %p, %d", object, priv->dispose_has_run);
-
-  if (priv->dispose_has_run)
-    return;
-
-  priv->dispose_has_run = TRUE;
-
-  if (priv->channel != NULL)
-    {
-      g_signal_handlers_disconnect_by_func (priv->channel,
-        tp_call_channel_invalidated_cb, object);
-
-      g_object_unref (priv->channel);
-      priv->channel = NULL;
-    }
-
-  if (priv->contact != NULL)
-      g_object_unref (priv->contact);
-
-  tp_clear_object (&priv->account);
-
-  if (G_OBJECT_CLASS (empathy_tp_call_parent_class)->dispose)
-    G_OBJECT_CLASS (empathy_tp_call_parent_class)->dispose (object);
-}
-
-static void
-tp_call_finalize (GObject *object)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (object);
-
-  DEBUG ("Finalizing: %p", object);
-
-  g_slice_free (EmpathyTpCallStream, priv->audio);
-  g_slice_free (EmpathyTpCallStream, priv->video);
-
-  (G_OBJECT_CLASS (empathy_tp_call_parent_class)->finalize) (object);
-}
-
-static void
-tp_call_set_property (GObject *object,
-                      guint prop_id,
-                      const GValue *value,
-                      GParamSpec *pspec)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (object);
-
-  switch (prop_id)
-    {
-    case PROP_ACCOUNT:
-      priv->account = g_value_dup_object (value);
-      break;
-    case PROP_CHANNEL:
-      priv->channel = g_value_dup_object (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-tp_call_get_property (GObject *object,
-                      guint prop_id,
-                      GValue *value,
-                      GParamSpec *pspec)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (object);
-
-  switch (prop_id)
-    {
-    case PROP_ACCOUNT:
-      g_value_set_object (value, priv->channel);
-      break;
-    case PROP_CHANNEL:
-      g_value_set_object (value, priv->channel);
-      break;
-    case PROP_CONTACT:
-      g_value_set_object (value, priv->contact);
-      break;
-    case PROP_STATUS:
-      g_value_set_uint (value, priv->status);
-      break;
-    case PROP_AUDIO_STREAM:
-      g_value_set_pointer (value, priv->audio);
-      break;
-    case PROP_VIDEO_STREAM:
-      g_value_set_pointer (value, priv->video);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-empathy_tp_call_class_init (EmpathyTpCallClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-  object_class->constructor = tp_call_constructor;
-  object_class->dispose = tp_call_dispose;
-  object_class->finalize = tp_call_finalize;
-  object_class->set_property = tp_call_set_property;
-  object_class->get_property = tp_call_get_property;
-
-  g_type_class_add_private (klass, sizeof (EmpathyTpCallPriv));
-
-  g_object_class_install_property (object_class, PROP_ACCOUNT,
-      g_param_spec_object ("account", "TpAccount", "TpAccount",
-      TP_TYPE_ACCOUNT,
-      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
-      G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (object_class, PROP_CHANNEL,
-      g_param_spec_object ("channel", "channel", "channel",
-      TP_TYPE_CHANNEL,
-      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
-  g_object_class_install_property (object_class, PROP_CONTACT,
-      g_param_spec_object ("contact", "Call contact", "Call contact",
-      EMPATHY_TYPE_CONTACT,
-      G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
-  g_object_class_install_property (object_class, PROP_STATUS,
-      g_param_spec_uint ("status", "Call status",
-      "Call status", 0, 255, 0, G_PARAM_READABLE | G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB));
-
-  g_object_class_install_property (object_class, PROP_AUDIO_STREAM,
-      g_param_spec_pointer ("audio-stream", "Audio stream data",
-      "Audio stream data",
-      G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
-  g_object_class_install_property (object_class, PROP_VIDEO_STREAM,
-      g_param_spec_pointer ("video-stream", "Video stream data",
-      "Video stream data",
-      G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
-  signals[AUDIO_STREAM_ERROR] =
-    g_signal_new ("audio-stream-error",
-      G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, 0,
-      NULL, NULL,
-      _empathy_marshal_VOID__UINT_STRING,
-      G_TYPE_NONE,
-      2, G_TYPE_UINT, G_TYPE_STRING);
-
-  signals[VIDEO_STREAM_ERROR] =
-    g_signal_new ("video-stream-error",
-      G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, 0,
-      NULL, NULL,
-      _empathy_marshal_VOID__UINT_STRING,
-      G_TYPE_NONE,
-      2, G_TYPE_UINT, G_TYPE_STRING);
-}
-
-static void
-empathy_tp_call_init (EmpathyTpCall *call)
-{
-  EmpathyTpCallPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (call,
-    EMPATHY_TYPE_TP_CALL, EmpathyTpCallPriv);
-
-  call->priv = priv;
-  priv->status = EMPATHY_TP_CALL_STATUS_READYING;
-  priv->contact = NULL;
-  priv->audio = g_slice_new0 (EmpathyTpCallStream);
-  priv->video = g_slice_new0 (EmpathyTpCallStream);
-  priv->audio->exists = FALSE;
-  priv->video->exists = FALSE;
-}
-
-EmpathyTpCall *
-empathy_tp_call_new (TpAccount *account,
-    TpChannel *channel)
-{
-  g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
-  g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
-
-  return g_object_new (EMPATHY_TYPE_TP_CALL,
-      "account", account,
-      "channel", channel,
-      NULL);
-}
-
-void
-empathy_tp_call_accept_incoming_call (EmpathyTpCall *call)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-  TpHandle self_handle;
-  GArray handles = {(gchar *) &self_handle, 1};
-
-  g_return_if_fail (EMPATHY_IS_TP_CALL (call));
-  g_return_if_fail (priv->status == EMPATHY_TP_CALL_STATUS_PENDING);
-
-  if (!priv->is_incoming)
-    return;
-
-  DEBUG ("Accepting incoming call");
-
-  self_handle = tp_channel_group_get_self_handle (priv->channel);
-  tp_cli_channel_interface_group_call_add_members (priv->channel, -1,
-      &handles, NULL, NULL, NULL, NULL, NULL);
-}
-
-void
-empathy_tp_call_close (EmpathyTpCall *call)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-
-  g_return_if_fail (EMPATHY_IS_TP_CALL (call));
-
-  if (priv->status == EMPATHY_TP_CALL_STATUS_CLOSED)
-      return;
-
-  DEBUG ("Closing channel");
-
-  tp_cli_channel_call_close (priv->channel, -1,
-      NULL, NULL, NULL, NULL);
-
-  priv->status = EMPATHY_TP_CALL_STATUS_CLOSED;
-  g_object_notify (G_OBJECT (call), "status");
-}
-
-void
-empathy_tp_call_request_video_stream_direction (EmpathyTpCall *call,
-                                                gboolean is_sending)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-  guint new_direction;
-
-  g_return_if_fail (EMPATHY_IS_TP_CALL (call));
-  g_return_if_fail (priv->status == EMPATHY_TP_CALL_STATUS_ACCEPTED);
-
-  DEBUG ("Requesting video stream direction - is_sending: %d", is_sending);
-
-  if (!priv->video->exists)
-    {
-      if (is_sending)
-          tp_call_request_streams_for_capabilities (call,
-              EMPATHY_CAPABILITIES_VIDEO);
-      return;
-    }
-
-  if (is_sending)
-      new_direction = priv->video->direction | TP_MEDIA_STREAM_DIRECTION_SEND;
-  else
-      new_direction = priv->video->direction & ~TP_MEDIA_STREAM_DIRECTION_SEND;
-
-  tp_cli_channel_type_streamed_media_call_request_stream_direction (priv->channel,
-      -1, priv->video->id, new_direction,
-      (tp_cli_channel_type_streamed_media_callback_for_request_stream_direction)
-      tp_call_async_cb, NULL, NULL, G_OBJECT (call));
-}
-
-void
-empathy_tp_call_start_tone (EmpathyTpCall *call, TpDTMFEvent event)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-
-  g_return_if_fail (EMPATHY_IS_TP_CALL (call));
-  g_return_if_fail (priv->status == EMPATHY_TP_CALL_STATUS_ACCEPTED);
-
-  if (!priv->audio->exists)
-      return;
-
-  tp_cli_channel_interface_dtmf_call_start_tone (priv->channel, -1,
-      priv->audio->id, event,
-      (tp_cli_channel_interface_dtmf_callback_for_start_tone) tp_call_async_cb,
-      "starting tone", NULL, G_OBJECT (call));
-}
-
-void
-empathy_tp_call_stop_tone (EmpathyTpCall *call)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-
-  g_return_if_fail (EMPATHY_IS_TP_CALL (call));
-  g_return_if_fail (priv->status == EMPATHY_TP_CALL_STATUS_ACCEPTED);
-
-  if (!priv->audio->exists)
-      return;
-
-  tp_cli_channel_interface_dtmf_call_stop_tone (priv->channel, -1,
-      priv->audio->id,
-      (tp_cli_channel_interface_dtmf_callback_for_stop_tone) tp_call_async_cb,
-      "stoping tone", NULL, G_OBJECT (call));
-}
-
-gboolean
-empathy_tp_call_has_dtmf (EmpathyTpCall *call)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-
-  g_return_val_if_fail (EMPATHY_IS_TP_CALL (call), FALSE);
-
-  return tp_proxy_has_interface_by_id (priv->channel,
-      TP_IFACE_QUARK_CHANNEL_INTERFACE_DTMF);
-}
-
-/**
- * empathy_tp_call_is_receiving_video:
- * @call: the call
- *
- * Indicates if the call is receiving video or not.
- *
- * Returns: %TRUE if the call is currently receiving video, %FALSE otherwise.
- */
-gboolean
-empathy_tp_call_is_receiving_video (EmpathyTpCall *call)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-
-  g_return_val_if_fail (EMPATHY_IS_TP_CALL (call), FALSE);
-
-  if (!priv->video->exists)
-    return FALSE;
-
-  return priv->video->direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE ?
-      TRUE : FALSE;
-}
-
-/**
- * empathy_tp_call_is_sending_video:
- * @call: the call
- *
- * Indicates if the call is sending video or not.
- *
- * Returns: %TRUE if the call is currently sending video, %FALSE otherwise.
- */
-gboolean
-empathy_tp_call_is_sending_video (EmpathyTpCall *call)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (call);
-
-  g_return_val_if_fail (EMPATHY_IS_TP_CALL (call), FALSE);
-
-  if (!priv->video->exists)
-    return FALSE;
-
-  return priv->video->direction & TP_MEDIA_STREAM_DIRECTION_SEND ?
-      TRUE : FALSE;
-}
-
-const gchar *
-empathy_tp_call_get_connection_manager (EmpathyTpCall *self)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (self);
-
-  return tp_account_get_connection_manager (priv->account);
-}
-
-gboolean
-empathy_tp_call_has_initial_video (EmpathyTpCall *self)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (self);
-  GHashTable *props;
-  gboolean initial_video;
-  gboolean valid;
-
-  if (priv->channel == NULL)
-    return FALSE;
-
-  g_object_get (priv->channel, "channel-properties", &props, NULL);
-
-  initial_video = tp_asv_get_boolean (props,
-    TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA ".InitialVideo", &valid);
-  if (!valid)
-    initial_video = FALSE;
-
-  g_hash_table_unref (props);
-  return initial_video;
-}
-
-static void
-leave_remove_members_cb (TpChannel *proxy,
-    const GError *error,
-    gpointer user_data,
-    GObject *weak_object)
-{
-  EmpathyTpCall *self = user_data;
-
-  if (error == NULL)
-    return;
-
-  DEBUG ("RemoveMembers failed (%s); closing the channel", error->message);
-  empathy_tp_call_close (self);
-}
-
-void
-empathy_tp_call_leave (EmpathyTpCall *self)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (self);
-  TpHandle self_handle;
-  GArray array = { (gchar *) &self_handle, 1 };
-
-  if (!tp_proxy_has_interface_by_id (priv->channel,
-        TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP))
-    {
-      empathy_tp_call_close (self);
-      return;
-    }
-
-  self_handle = tp_channel_group_get_self_handle (priv->channel);
-  if (self_handle == 0)
-    {
-      /* we are not member of the channel */
-      empathy_tp_call_close (self);
-      return;
-    }
-
-  tp_cli_channel_interface_group_call_remove_members (priv->channel, -1, &array,
-      "", leave_remove_members_cb, self, NULL, G_OBJECT (self));
-}
-
-EmpathyTpCallStatus
-empathy_tp_call_get_status (EmpathyTpCall *self)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (self);
-
-  return priv->status;
-}
-
-TpAccount *
-empathy_tp_call_get_account (EmpathyTpCall *self)
-{
-  EmpathyTpCallPriv *priv = GET_PRIV (self);
-
-  return priv->account;
-}
diff --git a/libempathy/empathy-tp-call.h b/libempathy/empathy-tp-call.h
deleted file mode 100644 (file)
index c633da3..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2007 Elliot Fairweather
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * 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
- *
- * Authors: Elliot Fairweather <elliot.fairweather@collabora.co.uk>
- *          Xavier Claessens <xclaesse@gmail.com>
- */
-
-#ifndef __EMPATHY_TP_CALL_H__
-#define __EMPATHY_TP_CALL_H__
-
-#include <glib.h>
-#include <telepathy-glib/channel.h>
-
-#include "empathy-contact.h"
-
-G_BEGIN_DECLS
-
-#define EMPATHY_TYPE_TP_CALL (empathy_tp_call_get_type ())
-#define EMPATHY_TP_CALL(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), \
-    EMPATHY_TYPE_TP_CALL, EmpathyTpCall))
-#define EMPATHY_TP_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
-    EMPATHY_TYPE_TP_CALL, EmpathyTpCallClass))
-#define EMPATHY_IS_TP_CALL(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), \
-    EMPATHY_TYPE_TP_CALL))
-#define EMPATHY_IS_TP_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
-    EMPATHY_TYPE_TP_CALL))
-#define EMPATHY_TP_CALL_GET_CLASS(object) \
-  (G_TYPE_INSTANCE_GET_CLASS ((object), \
-    EMPATHY_TYPE_TP_CALL, EmpathyTpCallClass))
-
-typedef struct _EmpathyTpCall EmpathyTpCall;
-typedef struct _EmpathyTpCallClass EmpathyTpCallClass;
-
-struct _EmpathyTpCall {
-  GObject parent;
-  gpointer priv;
-};
-
-struct _EmpathyTpCallClass {
-  GObjectClass parent_class;
-};
-
-typedef enum
-{
-  EMPATHY_TP_CALL_STATUS_READYING,
-  EMPATHY_TP_CALL_STATUS_PENDING,
-  EMPATHY_TP_CALL_STATUS_ACCEPTED,
-  EMPATHY_TP_CALL_STATUS_CLOSED
-} EmpathyTpCallStatus;
-
-typedef struct
-{
-  gboolean exists;
-  guint id;
-  guint state;
-  guint direction;
-} EmpathyTpCallStream;
-
-GType empathy_tp_call_get_type (void) G_GNUC_CONST;
-EmpathyTpCall *empathy_tp_call_new (TpAccount *account,
-    TpChannel *channel);
-void empathy_tp_call_close (EmpathyTpCall *call);
-
-void empathy_tp_call_accept_incoming_call (EmpathyTpCall *call);
-void empathy_tp_call_request_video_stream_direction (EmpathyTpCall *call,
-    gboolean is_sending);
-void empathy_tp_call_start_tone (EmpathyTpCall *call, TpDTMFEvent event);
-void empathy_tp_call_stop_tone (EmpathyTpCall *call);
-gboolean empathy_tp_call_has_dtmf (EmpathyTpCall *call);
-gboolean empathy_tp_call_is_receiving_video (EmpathyTpCall *call);
-gboolean empathy_tp_call_is_sending_video (EmpathyTpCall *call);
-
-const gchar * empathy_tp_call_get_connection_manager (EmpathyTpCall *self);
-
-gboolean empathy_tp_call_has_initial_video (EmpathyTpCall *self);
-
-void empathy_tp_call_leave (EmpathyTpCall *self);
-
-EmpathyTpCallStatus empathy_tp_call_get_status (EmpathyTpCall *self);
-
-TpAccount * empathy_tp_call_get_account (EmpathyTpCall *self);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_TP_CALL_H__ */
diff --git a/libempathy/empathy-tp-streamed-media.c b/libempathy/empathy-tp-streamed-media.c
new file mode 100644 (file)
index 0000000..b79e4b6
--- /dev/null
@@ -0,0 +1,855 @@
+/*
+ * Copyright (C) 2007 Elliot Fairweather
+ * Copyright (C) 2007-2008 Collabora Ltd.
+ *
+ * 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
+ *
+ * Authors: Elliot Fairweather <elliot.fairweather@collabora.co.uk>
+ *          Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include <string.h>
+
+#include <telepathy-glib/proxy-subclass.h>
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/util.h>
+
+#include "empathy-tp-streamed-media.h"
+#include "empathy-tp-contact-factory.h"
+#include "empathy-utils.h"
+#include "empathy-marshal.h"
+
+#define DEBUG_FLAG EMPATHY_DEBUG_VOIP
+#include "empathy-debug.h"
+
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpStreamedMedia)
+typedef struct
+{
+  gboolean dispose_has_run;
+  TpAccount *account;
+  TpChannel *channel;
+  EmpathyContact *contact;
+  gboolean is_incoming;
+  guint status;
+
+  EmpathyTpStreamedMediaStream *audio;
+  EmpathyTpStreamedMediaStream *video;
+} EmpathyTpStreamedMediaPriv;
+
+/* signal enum */
+enum {
+  AUDIO_STREAM_ERROR,
+  VIDEO_STREAM_ERROR,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+enum
+{
+  PROP_0,
+  PROP_ACCOUNT,
+  PROP_CHANNEL,
+  PROP_CONTACT,
+  PROP_STATUS,
+  PROP_AUDIO_STREAM,
+  PROP_VIDEO_STREAM
+};
+
+G_DEFINE_TYPE (EmpathyTpStreamedMedia, empathy_tp_streamed_media, G_TYPE_OBJECT)
+
+static void
+tp_streamed_media_add_stream (EmpathyTpStreamedMedia *call,
+                    guint stream_id,
+                    guint contact_handle,
+                    guint stream_type,
+                    guint stream_state,
+                    guint stream_direction)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+
+  switch (stream_type)
+    {
+      case TP_MEDIA_STREAM_TYPE_AUDIO:
+        DEBUG ("Audio stream - id: %d, state: %d, direction: %d",
+            stream_id, stream_state, stream_direction);
+        priv->audio->exists = TRUE;
+        priv->audio->id = stream_id;
+        priv->audio->state = stream_state;
+        priv->audio->direction = stream_direction;
+        g_object_notify (G_OBJECT (call), "audio-stream");
+        break;
+      case TP_MEDIA_STREAM_TYPE_VIDEO:
+        DEBUG ("Video stream - id: %d, state: %d, direction: %d",
+            stream_id, stream_state, stream_direction);
+        priv->video->exists = TRUE;
+        priv->video->id = stream_id;
+        priv->video->state = stream_state;
+        priv->video->direction = stream_direction;
+        g_object_notify (G_OBJECT (call), "video-stream");
+        break;
+      default:
+        DEBUG ("Unknown stream type: %d", stream_type);
+    }
+}
+
+static void
+tp_streamed_media_stream_added_cb (TpChannel *channel,
+                         guint stream_id,
+                         guint contact_handle,
+                         guint stream_type,
+                         gpointer user_data,
+                         GObject *call)
+{
+  DEBUG ("Stream added - stream id: %d, contact handle: %d, stream type: %d",
+      stream_id, contact_handle, stream_type);
+
+  tp_streamed_media_add_stream (EMPATHY_TP_STREAMED_MEDIA (call), stream_id, contact_handle,
+      stream_type, TP_MEDIA_STREAM_STATE_DISCONNECTED,
+      TP_MEDIA_STREAM_DIRECTION_NONE);
+}
+
+static void
+tp_streamed_media_stream_removed_cb (TpChannel *channel,
+                           guint stream_id,
+                           gpointer user_data,
+                           GObject *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+
+  DEBUG ("Stream removed - stream id: %d", stream_id);
+
+  if (stream_id == priv->audio->id)
+    {
+      priv->audio->exists = FALSE;
+      g_object_notify (call, "audio-stream");
+    }
+  else if (stream_id == priv->video->id)
+    {
+      priv->video->exists = FALSE;
+      g_object_notify (call, "video-stream");
+    }
+}
+
+static void
+tp_streamed_media_stream_state_changed_cb (TpChannel *proxy,
+                                 guint stream_id,
+                                 guint stream_state,
+                                 gpointer user_data,
+                                 GObject *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+
+  DEBUG ("Stream state changed - stream id: %d, state state: %d",
+      stream_id, stream_state);
+
+  if (stream_id == priv->audio->id)
+    {
+      priv->audio->state = stream_state;
+      g_object_notify (call, "audio-stream");
+    }
+  else if (stream_id == priv->video->id)
+    {
+      priv->video->state = stream_state;
+      g_object_notify (call, "video-stream");
+    }
+}
+
+static void
+tp_streamed_media_stream_direction_changed_cb (TpChannel *channel,
+                                     guint stream_id,
+                                     guint stream_direction,
+                                     guint pending_flags,
+                                     gpointer user_data,
+                                     GObject *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+
+  DEBUG ("Stream direction changed - stream: %d, direction: %d",
+      stream_id, stream_direction);
+
+  if (stream_id == priv->audio->id)
+    {
+      priv->audio->direction = stream_direction;
+      g_object_notify (call, "audio-stream");
+    }
+  else if (stream_id == priv->video->id)
+    {
+      priv->video->direction = stream_direction;
+      g_object_notify (call, "video-stream");
+    }
+}
+
+static void
+tp_streamed_media_request_streams_cb (TpChannel *channel,
+                            const GPtrArray *streams,
+                            const GError *error,
+                            gpointer user_data,
+                            GObject *call)
+{
+  guint i;
+
+  if (error)
+    {
+      DEBUG ("Error requesting streams: %s", error->message);
+      return;
+    }
+
+  for (i = 0; i < streams->len; i++)
+    {
+      GValueArray *values;
+      guint stream_id;
+      guint contact_handle;
+      guint stream_type;
+      guint stream_state;
+      guint stream_direction;
+
+      values = g_ptr_array_index (streams, i);
+      stream_id = g_value_get_uint (g_value_array_get_nth (values, 0));
+      contact_handle = g_value_get_uint (g_value_array_get_nth (values, 1));
+      stream_type = g_value_get_uint (g_value_array_get_nth (values, 2));
+      stream_state = g_value_get_uint (g_value_array_get_nth (values, 3));
+      stream_direction = g_value_get_uint (g_value_array_get_nth (values, 4));
+
+      tp_streamed_media_add_stream (EMPATHY_TP_STREAMED_MEDIA (call), stream_id, contact_handle,
+          stream_type, stream_state, stream_direction);
+  }
+}
+
+static void
+tp_streamed_media_request_streams_for_capabilities (EmpathyTpStreamedMedia *call,
+                                          EmpathyCapabilities capabilities)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+  GArray *stream_types;
+  guint handle;
+  guint stream_type;
+
+  if (capabilities == EMPATHY_CAPABILITIES_UNKNOWN)
+      capabilities = EMPATHY_CAPABILITIES_AUDIO | EMPATHY_CAPABILITIES_VIDEO;
+
+  DEBUG ("Requesting new stream for capabilities %d",
+      capabilities);
+
+  stream_types = g_array_new (FALSE, FALSE, sizeof (guint));
+  handle = empathy_contact_get_handle (priv->contact);
+
+  if (capabilities & EMPATHY_CAPABILITIES_AUDIO)
+    {
+      stream_type = TP_MEDIA_STREAM_TYPE_AUDIO;
+      g_array_append_val (stream_types, stream_type);
+    }
+  if (capabilities & EMPATHY_CAPABILITIES_VIDEO)
+    {
+      stream_type = TP_MEDIA_STREAM_TYPE_VIDEO;
+      g_array_append_val (stream_types, stream_type);
+    }
+
+  tp_cli_channel_type_streamed_media_call_request_streams (priv->channel, -1,
+      handle, stream_types, tp_streamed_media_request_streams_cb, NULL, NULL,
+      G_OBJECT (call));
+
+  g_array_free (stream_types, TRUE);
+}
+
+static void
+tp_streamed_media_got_contact_cb (TpConnection            *connection,
+                        EmpathyContact          *contact,
+                        const GError            *error,
+                        gpointer                 user_data,
+                        GObject                 *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+
+  if (error)
+    {
+      DEBUG ("Error: %s", error->message);
+      return;
+    }
+
+  priv->contact = g_object_ref (contact);
+
+  if (priv->status < EMPATHY_TP_STREAMED_MEDIA_STATUS_PENDING)
+    {
+      priv->status = EMPATHY_TP_STREAMED_MEDIA_STATUS_PENDING;
+      g_object_notify (G_OBJECT (call), "status");
+    }
+
+  g_object_notify (G_OBJECT (call), "contact");
+}
+
+static void
+tp_streamed_media_update_status (EmpathyTpStreamedMedia *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+  TpHandle self_handle;
+  const TpIntSet *set;
+  TpIntSetIter iter;
+
+  g_object_ref (call);
+
+  self_handle = tp_channel_group_get_self_handle (priv->channel);
+  set = tp_channel_group_get_members (priv->channel);
+  tp_intset_iter_init (&iter, set);
+  while (tp_intset_iter_next (&iter))
+    {
+      if (priv->status == EMPATHY_TP_STREAMED_MEDIA_STATUS_PENDING &&
+          ((priv->is_incoming && iter.element == self_handle) ||
+           (!priv->is_incoming && iter.element != self_handle)))
+        {
+          priv->status = EMPATHY_TP_STREAMED_MEDIA_STATUS_ACCEPTED;
+          g_object_notify (G_OBJECT (call), "status");
+        }
+    }
+
+  g_object_unref (call);
+}
+
+static void
+tp_streamed_media_channel_invalidated_cb (TpChannel     *channel,
+                                GQuark         domain,
+                                gint           code,
+                                gchar         *message,
+                                EmpathyTpStreamedMedia *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+
+  DEBUG ("Channel invalidated: %s", message);
+  priv->status = EMPATHY_TP_STREAMED_MEDIA_STATUS_CLOSED;
+  g_object_notify (G_OBJECT (call), "status");
+}
+
+static void
+tp_streamed_media_async_cb (TpProxy *proxy,
+                  const GError *error,
+                  gpointer user_data,
+                  GObject *call)
+{
+  if (error)
+      DEBUG ("Error %s: %s", (gchar *) user_data, error->message);
+}
+
+static void
+tp_streamed_media_stream_error_cb (TpChannel *channel,
+    guint stream_id,
+    guint error_code,
+    const gchar *msg,
+    gpointer user_data,
+    GObject *call)
+{
+  EmpathyTpStreamedMedia *self = EMPATHY_TP_STREAMED_MEDIA (call);
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (self);
+
+  DEBUG ("Stream error on stream %u: %s (code: %u)", stream_id, msg,
+      error_code);
+
+  if (priv->audio->id == stream_id)
+    {
+      g_signal_emit (call, signals[AUDIO_STREAM_ERROR], 0, error_code, msg);
+    }
+  else if (priv->video->id == stream_id)
+    {
+      g_signal_emit (call, signals[VIDEO_STREAM_ERROR], 0, error_code, msg);
+    }
+  else
+    {
+      DEBUG ("Unknown stream id: %u", stream_id);
+    }
+}
+
+static GObject *
+tp_streamed_media_constructor (GType type,
+                     guint n_construct_params,
+                     GObjectConstructParam *construct_params)
+{
+  GObject *object;
+  EmpathyTpStreamedMedia *call;
+  EmpathyTpStreamedMediaPriv *priv;
+
+  object = G_OBJECT_CLASS (empathy_tp_streamed_media_parent_class)->constructor (type,
+      n_construct_params, construct_params);
+
+  call = EMPATHY_TP_STREAMED_MEDIA (object);
+  priv = GET_PRIV (call);
+
+  /* Setup streamed media channel */
+  g_signal_connect (priv->channel, "invalidated",
+      G_CALLBACK (tp_streamed_media_channel_invalidated_cb), call);
+  tp_cli_channel_type_streamed_media_connect_to_stream_added (priv->channel,
+      tp_streamed_media_stream_added_cb, NULL, NULL, G_OBJECT (call), NULL);
+  tp_cli_channel_type_streamed_media_connect_to_stream_removed (priv->channel,
+      tp_streamed_media_stream_removed_cb, NULL, NULL, G_OBJECT (call), NULL);
+  tp_cli_channel_type_streamed_media_connect_to_stream_state_changed (priv->channel,
+      tp_streamed_media_stream_state_changed_cb, NULL, NULL, G_OBJECT (call), NULL);
+  tp_cli_channel_type_streamed_media_connect_to_stream_direction_changed (priv->channel,
+      tp_streamed_media_stream_direction_changed_cb, NULL, NULL, G_OBJECT (call), NULL);
+  tp_cli_channel_type_streamed_media_connect_to_stream_error (priv->channel,
+      tp_streamed_media_stream_error_cb, NULL, NULL, G_OBJECT (call), NULL);
+  tp_cli_channel_type_streamed_media_call_list_streams (priv->channel, -1,
+      tp_streamed_media_request_streams_cb, NULL, NULL, G_OBJECT (call));
+
+  /* Is the call incoming? */
+  priv->is_incoming = !tp_channel_get_requested (priv->channel);
+
+  /* Get the remote contact */
+  empathy_tp_contact_factory_get_from_handle (
+      tp_channel_borrow_connection (priv->channel),
+      tp_channel_get_handle (priv->channel, NULL), tp_streamed_media_got_contact_cb,
+      NULL, NULL, object);
+
+  /* Update status when members changes */
+  tp_streamed_media_update_status (call);
+  tp_g_signal_connect_object (priv->channel, "group-members-changed",
+      G_CALLBACK (tp_streamed_media_update_status), call, G_CONNECT_SWAPPED);
+
+  return object;
+}
+static void
+tp_streamed_media_dispose (GObject *object)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (object);
+
+  DEBUG ("Disposing: %p, %d", object, priv->dispose_has_run);
+
+  if (priv->dispose_has_run)
+    return;
+
+  priv->dispose_has_run = TRUE;
+
+  if (priv->channel != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (priv->channel,
+        tp_streamed_media_channel_invalidated_cb, object);
+
+      g_object_unref (priv->channel);
+      priv->channel = NULL;
+    }
+
+  if (priv->contact != NULL)
+      g_object_unref (priv->contact);
+
+  tp_clear_object (&priv->account);
+
+  if (G_OBJECT_CLASS (empathy_tp_streamed_media_parent_class)->dispose)
+    G_OBJECT_CLASS (empathy_tp_streamed_media_parent_class)->dispose (object);
+}
+
+static void
+tp_streamed_media_finalize (GObject *object)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (object);
+
+  DEBUG ("Finalizing: %p", object);
+
+  g_slice_free (EmpathyTpStreamedMediaStream, priv->audio);
+  g_slice_free (EmpathyTpStreamedMediaStream, priv->video);
+
+  (G_OBJECT_CLASS (empathy_tp_streamed_media_parent_class)->finalize) (object);
+}
+
+static void
+tp_streamed_media_set_property (GObject *object,
+                      guint prop_id,
+                      const GValue *value,
+                      GParamSpec *pspec)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (object);
+
+  switch (prop_id)
+    {
+    case PROP_ACCOUNT:
+      priv->account = g_value_dup_object (value);
+      break;
+    case PROP_CHANNEL:
+      priv->channel = g_value_dup_object (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+tp_streamed_media_get_property (GObject *object,
+                      guint prop_id,
+                      GValue *value,
+                      GParamSpec *pspec)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (object);
+
+  switch (prop_id)
+    {
+    case PROP_ACCOUNT:
+      g_value_set_object (value, priv->channel);
+      break;
+    case PROP_CHANNEL:
+      g_value_set_object (value, priv->channel);
+      break;
+    case PROP_CONTACT:
+      g_value_set_object (value, priv->contact);
+      break;
+    case PROP_STATUS:
+      g_value_set_uint (value, priv->status);
+      break;
+    case PROP_AUDIO_STREAM:
+      g_value_set_pointer (value, priv->audio);
+      break;
+    case PROP_VIDEO_STREAM:
+      g_value_set_pointer (value, priv->video);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+empathy_tp_streamed_media_class_init (EmpathyTpStreamedMediaClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructor = tp_streamed_media_constructor;
+  object_class->dispose = tp_streamed_media_dispose;
+  object_class->finalize = tp_streamed_media_finalize;
+  object_class->set_property = tp_streamed_media_set_property;
+  object_class->get_property = tp_streamed_media_get_property;
+
+  g_type_class_add_private (klass, sizeof (EmpathyTpStreamedMediaPriv));
+
+  g_object_class_install_property (object_class, PROP_ACCOUNT,
+      g_param_spec_object ("account", "TpAccount", "TpAccount",
+      TP_TYPE_ACCOUNT,
+      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
+      G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (object_class, PROP_CHANNEL,
+      g_param_spec_object ("channel", "channel", "channel",
+      TP_TYPE_CHANNEL,
+      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+  g_object_class_install_property (object_class, PROP_CONTACT,
+      g_param_spec_object ("contact", "Call contact", "Call contact",
+      EMPATHY_TYPE_CONTACT,
+      G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+  g_object_class_install_property (object_class, PROP_STATUS,
+      g_param_spec_uint ("status", "Call status",
+      "Call status", 0, 255, 0, G_PARAM_READABLE | G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB));
+
+  g_object_class_install_property (object_class, PROP_AUDIO_STREAM,
+      g_param_spec_pointer ("audio-stream", "Audio stream data",
+      "Audio stream data",
+      G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+  g_object_class_install_property (object_class, PROP_VIDEO_STREAM,
+      g_param_spec_pointer ("video-stream", "Video stream data",
+      "Video stream data",
+      G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+  signals[AUDIO_STREAM_ERROR] =
+    g_signal_new ("audio-stream-error",
+      G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, 0,
+      NULL, NULL,
+      _empathy_marshal_VOID__UINT_STRING,
+      G_TYPE_NONE,
+      2, G_TYPE_UINT, G_TYPE_STRING);
+
+  signals[VIDEO_STREAM_ERROR] =
+    g_signal_new ("video-stream-error",
+      G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, 0,
+      NULL, NULL,
+      _empathy_marshal_VOID__UINT_STRING,
+      G_TYPE_NONE,
+      2, G_TYPE_UINT, G_TYPE_STRING);
+}
+
+static void
+empathy_tp_streamed_media_init (EmpathyTpStreamedMedia *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (call,
+    EMPATHY_TYPE_TP_STREAMED_MEDIA, EmpathyTpStreamedMediaPriv);
+
+  call->priv = priv;
+  priv->status = EMPATHY_TP_STREAMED_MEDIA_STATUS_READYING;
+  priv->contact = NULL;
+  priv->audio = g_slice_new0 (EmpathyTpStreamedMediaStream);
+  priv->video = g_slice_new0 (EmpathyTpStreamedMediaStream);
+  priv->audio->exists = FALSE;
+  priv->video->exists = FALSE;
+}
+
+EmpathyTpStreamedMedia *
+empathy_tp_streamed_media_new (TpAccount *account,
+    TpChannel *channel)
+{
+  g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
+  g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
+
+  return g_object_new (EMPATHY_TYPE_TP_STREAMED_MEDIA,
+      "account", account,
+      "channel", channel,
+      NULL);
+}
+
+void
+empathy_tp_streamed_media_accept_incoming_call (EmpathyTpStreamedMedia *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+  TpHandle self_handle;
+  GArray handles = {(gchar *) &self_handle, 1};
+
+  g_return_if_fail (EMPATHY_IS_TP_STREAMED_MEDIA (call));
+  g_return_if_fail (priv->status == EMPATHY_TP_STREAMED_MEDIA_STATUS_PENDING);
+
+  if (!priv->is_incoming)
+    return;
+
+  DEBUG ("Accepting incoming call");
+
+  self_handle = tp_channel_group_get_self_handle (priv->channel);
+  tp_cli_channel_interface_group_call_add_members (priv->channel, -1,
+      &handles, NULL, NULL, NULL, NULL, NULL);
+}
+
+void
+empathy_tp_streamed_media_close (EmpathyTpStreamedMedia *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+
+  g_return_if_fail (EMPATHY_IS_TP_STREAMED_MEDIA (call));
+
+  if (priv->status == EMPATHY_TP_STREAMED_MEDIA_STATUS_CLOSED)
+      return;
+
+  DEBUG ("Closing channel");
+
+  tp_cli_channel_call_close (priv->channel, -1,
+      NULL, NULL, NULL, NULL);
+
+  priv->status = EMPATHY_TP_STREAMED_MEDIA_STATUS_CLOSED;
+  g_object_notify (G_OBJECT (call), "status");
+}
+
+void
+empathy_tp_streamed_media_request_video_stream_direction (EmpathyTpStreamedMedia *call,
+                                                gboolean is_sending)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+  guint new_direction;
+
+  g_return_if_fail (EMPATHY_IS_TP_STREAMED_MEDIA (call));
+  g_return_if_fail (priv->status == EMPATHY_TP_STREAMED_MEDIA_STATUS_ACCEPTED);
+
+  DEBUG ("Requesting video stream direction - is_sending: %d", is_sending);
+
+  if (!priv->video->exists)
+    {
+      if (is_sending)
+          tp_streamed_media_request_streams_for_capabilities (call,
+              EMPATHY_CAPABILITIES_VIDEO);
+      return;
+    }
+
+  if (is_sending)
+      new_direction = priv->video->direction | TP_MEDIA_STREAM_DIRECTION_SEND;
+  else
+      new_direction = priv->video->direction & ~TP_MEDIA_STREAM_DIRECTION_SEND;
+
+  tp_cli_channel_type_streamed_media_call_request_stream_direction (priv->channel,
+      -1, priv->video->id, new_direction,
+      (tp_cli_channel_type_streamed_media_callback_for_request_stream_direction)
+      tp_streamed_media_async_cb, NULL, NULL, G_OBJECT (call));
+}
+
+void
+empathy_tp_streamed_media_start_tone (EmpathyTpStreamedMedia *call, TpDTMFEvent event)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+
+  g_return_if_fail (EMPATHY_IS_TP_STREAMED_MEDIA (call));
+  g_return_if_fail (priv->status == EMPATHY_TP_STREAMED_MEDIA_STATUS_ACCEPTED);
+
+  if (!priv->audio->exists)
+      return;
+
+  tp_cli_channel_interface_dtmf_call_start_tone (priv->channel, -1,
+      priv->audio->id, event,
+      (tp_cli_channel_interface_dtmf_callback_for_start_tone) tp_streamed_media_async_cb,
+      "starting tone", NULL, G_OBJECT (call));
+}
+
+void
+empathy_tp_streamed_media_stop_tone (EmpathyTpStreamedMedia *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+
+  g_return_if_fail (EMPATHY_IS_TP_STREAMED_MEDIA (call));
+  g_return_if_fail (priv->status == EMPATHY_TP_STREAMED_MEDIA_STATUS_ACCEPTED);
+
+  if (!priv->audio->exists)
+      return;
+
+  tp_cli_channel_interface_dtmf_call_stop_tone (priv->channel, -1,
+      priv->audio->id,
+      (tp_cli_channel_interface_dtmf_callback_for_stop_tone) tp_streamed_media_async_cb,
+      "stoping tone", NULL, G_OBJECT (call));
+}
+
+gboolean
+empathy_tp_streamed_media_has_dtmf (EmpathyTpStreamedMedia *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+
+  g_return_val_if_fail (EMPATHY_IS_TP_STREAMED_MEDIA (call), FALSE);
+
+  return tp_proxy_has_interface_by_id (priv->channel,
+      TP_IFACE_QUARK_CHANNEL_INTERFACE_DTMF);
+}
+
+/**
+ * empathy_tp_streamed_media_is_receiving_video:
+ * @call: the call
+ *
+ * Indicates if the call is receiving video or not.
+ *
+ * Returns: %TRUE if the call is currently receiving video, %FALSE otherwise.
+ */
+gboolean
+empathy_tp_streamed_media_is_receiving_video (EmpathyTpStreamedMedia *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+
+  g_return_val_if_fail (EMPATHY_IS_TP_STREAMED_MEDIA (call), FALSE);
+
+  if (!priv->video->exists)
+    return FALSE;
+
+  return priv->video->direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE ?
+      TRUE : FALSE;
+}
+
+/**
+ * empathy_tp_streamed_media_is_sending_video:
+ * @call: the call
+ *
+ * Indicates if the call is sending video or not.
+ *
+ * Returns: %TRUE if the call is currently sending video, %FALSE otherwise.
+ */
+gboolean
+empathy_tp_streamed_media_is_sending_video (EmpathyTpStreamedMedia *call)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (call);
+
+  g_return_val_if_fail (EMPATHY_IS_TP_STREAMED_MEDIA (call), FALSE);
+
+  if (!priv->video->exists)
+    return FALSE;
+
+  return priv->video->direction & TP_MEDIA_STREAM_DIRECTION_SEND ?
+      TRUE : FALSE;
+}
+
+const gchar *
+empathy_tp_streamed_media_get_connection_manager (EmpathyTpStreamedMedia *self)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (self);
+
+  return tp_account_get_connection_manager (priv->account);
+}
+
+gboolean
+empathy_tp_streamed_media_has_initial_video (EmpathyTpStreamedMedia *self)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (self);
+  GHashTable *props;
+  gboolean initial_video;
+  gboolean valid;
+
+  if (priv->channel == NULL)
+    return FALSE;
+
+  g_object_get (priv->channel, "channel-properties", &props, NULL);
+
+  initial_video = tp_asv_get_boolean (props,
+    TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA ".InitialVideo", &valid);
+  if (!valid)
+    initial_video = FALSE;
+
+  g_hash_table_unref (props);
+  return initial_video;
+}
+
+static void
+leave_remove_members_cb (TpChannel *proxy,
+    const GError *error,
+    gpointer user_data,
+    GObject *weak_object)
+{
+  EmpathyTpStreamedMedia *self = user_data;
+
+  if (error == NULL)
+    return;
+
+  DEBUG ("RemoveMembers failed (%s); closing the channel", error->message);
+  empathy_tp_streamed_media_close (self);
+}
+
+void
+empathy_tp_streamed_media_leave (EmpathyTpStreamedMedia *self)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (self);
+  TpHandle self_handle;
+  GArray array = { (gchar *) &self_handle, 1 };
+
+  if (!tp_proxy_has_interface_by_id (priv->channel,
+        TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP))
+    {
+      empathy_tp_streamed_media_close (self);
+      return;
+    }
+
+  self_handle = tp_channel_group_get_self_handle (priv->channel);
+  if (self_handle == 0)
+    {
+      /* we are not member of the channel */
+      empathy_tp_streamed_media_close (self);
+      return;
+    }
+
+  tp_cli_channel_interface_group_call_remove_members (priv->channel, -1, &array,
+      "", leave_remove_members_cb, self, NULL, G_OBJECT (self));
+}
+
+EmpathyTpStreamedMediaStatus
+empathy_tp_streamed_media_get_status (EmpathyTpStreamedMedia *self)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (self);
+
+  return priv->status;
+}
+
+TpAccount *
+empathy_tp_streamed_media_get_account (EmpathyTpStreamedMedia *self)
+{
+  EmpathyTpStreamedMediaPriv *priv = GET_PRIV (self);
+
+  return priv->account;
+}
diff --git a/libempathy/empathy-tp-streamed-media.h b/libempathy/empathy-tp-streamed-media.h
new file mode 100644 (file)
index 0000000..35612b2
--- /dev/null
@@ -0,0 +1,113 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Elliot Fairweather
+ * Copyright (C) 2007-2008 Collabora Ltd.
+ *
+ * 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
+ *
+ * Authors: Elliot Fairweather <elliot.fairweather@collabora.co.uk>
+ *          Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#ifndef __EMPATHY_TP_STREAMED_MEDIA_H__
+#define __EMPATHY_TP_STREAMED_MEDIA_H__
+
+#include <glib.h>
+#include <telepathy-glib/channel.h>
+
+#include "empathy-contact.h"
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_TP_STREAMED_MEDIA (empathy_tp_streamed_media_get_type ())
+#define EMPATHY_TP_STREAMED_MEDIA(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), \
+    EMPATHY_TYPE_TP_STREAMED_MEDIA, EmpathyTpStreamedMedia))
+#define EMPATHY_TP_STREAMED_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
+    EMPATHY_TYPE_TP_STREAMED_MEDIA, EmpathyTpStreamedMediaClass))
+#define EMPATHY_IS_TP_STREAMED_MEDIA(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), \
+    EMPATHY_TYPE_TP_STREAMED_MEDIA))
+#define EMPATHY_IS_TP_STREAMED_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+    EMPATHY_TYPE_TP_STREAMED_MEDIA))
+#define EMPATHY_TP_STREAMED_MEDIA_GET_CLASS(object) \
+  (G_TYPE_INSTANCE_GET_CLASS ((object), \
+    EMPATHY_TYPE_TP_STREAMED_MEDIA, EmpathyTpStreamedMediaClass))
+
+typedef struct _EmpathyTpStreamedMedia EmpathyTpStreamedMedia;
+typedef struct _EmpathyTpStreamedMediaClass EmpathyTpStreamedMediaClass;
+
+struct _EmpathyTpStreamedMedia {
+  GObject parent;
+  gpointer priv;
+};
+
+struct _EmpathyTpStreamedMediaClass {
+  GObjectClass parent_class;
+};
+
+typedef enum
+{
+  EMPATHY_TP_STREAMED_MEDIA_STATUS_READYING,
+  EMPATHY_TP_STREAMED_MEDIA_STATUS_PENDING,
+  EMPATHY_TP_STREAMED_MEDIA_STATUS_ACCEPTED,
+  EMPATHY_TP_STREAMED_MEDIA_STATUS_CLOSED
+} EmpathyTpStreamedMediaStatus;
+
+typedef struct
+{
+  gboolean exists;
+  guint id;
+  guint state;
+  guint direction;
+} EmpathyTpStreamedMediaStream;
+
+GType empathy_tp_streamed_media_get_type (void) G_GNUC_CONST;
+EmpathyTpStreamedMedia *empathy_tp_streamed_media_new (TpAccount *account,
+    TpChannel *channel);
+void empathy_tp_streamed_media_close (EmpathyTpStreamedMedia *streamed_media);
+
+void empathy_tp_streamed_media_accept_incoming_call (
+    EmpathyTpStreamedMedia *streamed_media);
+void empathy_tp_streamed_media_request_video_stream_direction (
+    EmpathyTpStreamedMedia *streamed_media,
+    gboolean is_sending);
+void empathy_tp_streamed_media_start_tone (
+    EmpathyTpStreamedMedia *streamed_media,
+    TpDTMFEvent event);
+void empathy_tp_streamed_media_stop_tone (
+    EmpathyTpStreamedMedia *streamed_media);
+gboolean empathy_tp_streamed_media_has_dtmf (
+    EmpathyTpStreamedMedia *streamed_media);
+gboolean empathy_tp_streamed_media_is_receiving_video (
+    EmpathyTpStreamedMedia *streamed_media);
+gboolean empathy_tp_streamed_media_is_sending_video (
+    EmpathyTpStreamedMedia *streamed_media);
+
+const gchar * empathy_tp_streamed_media_get_connection_manager (
+    EmpathyTpStreamedMedia *self);
+
+gboolean empathy_tp_streamed_media_has_initial_video (
+    EmpathyTpStreamedMedia *self);
+
+void empathy_tp_streamed_media_leave (EmpathyTpStreamedMedia *self);
+
+EmpathyTpStreamedMediaStatus empathy_tp_streamed_media_get_status (
+    EmpathyTpStreamedMedia *self);
+
+TpAccount * empathy_tp_streamed_media_get_account (
+    EmpathyTpStreamedMedia *self);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_TP_STREAMED_MEDIA_H__ */
index 3730e43a8fc74ac62bd4ce502d14b4d22eec66ce..d089c6fd55b3c6459c59bfc0731cfd87243252c5 100644 (file)
@@ -50,7 +50,6 @@
 #include "empathy-individual-manager.h"
 #include "empathy-dispatcher.h"
 #include "empathy-presence-manager.h"
-#include "empathy-tp-call.h"
 #include "empathy-tp-contact-factory.h"
 
 #include <extensions/extensions.h>
index d500123155f17ebe3e708a2acdf8178cb0003e07..2b9c48ce09855d9e75343c11f71f69f0b68dac41 100644 (file)
@@ -280,7 +280,7 @@ static void empathy_call_window_restart_call (EmpathyCallWindow *window);
 static void empathy_call_window_status_message (EmpathyCallWindow *window,
   gchar *message);
 
-static void empathy_call_window_update_avatars_visibility (EmpathyTpCall *call,
+static void empathy_call_window_update_avatars_visibility (EmpathyTpStreamedMedia *call,
   EmpathyCallWindow *window);
 
 static gboolean empathy_call_window_bus_message (GstBus *bus,
@@ -342,7 +342,7 @@ static void
 dtmf_button_pressed_cb (GtkButton *button, EmpathyCallWindow *window)
 {
   EmpathyCallWindowPriv *priv = GET_PRIV (window);
-  EmpathyTpCall *call;
+  EmpathyTpStreamedMedia *call;
   GQuark button_quark;
   TpDTMFEvent event;
 
@@ -352,7 +352,7 @@ dtmf_button_pressed_cb (GtkButton *button, EmpathyCallWindow *window)
   event = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (button),
     button_quark));
 
-  empathy_tp_call_start_tone (call, event);
+  empathy_tp_streamed_media_start_tone (call, event);
 
   g_object_unref (call);
 }
@@ -361,11 +361,11 @@ static void
 dtmf_button_released_cb (GtkButton *button, EmpathyCallWindow *window)
 {
   EmpathyCallWindowPriv *priv = GET_PRIV (window);
-  EmpathyTpCall *call;
+  EmpathyTpStreamedMedia *call;
 
   g_object_get (priv->handler, "tp-call", &call, NULL);
 
-  empathy_tp_call_stop_tone (call);
+  empathy_tp_streamed_media_stop_tone (call);
 
   g_object_unref (call);
 }
@@ -1577,7 +1577,7 @@ empathy_call_window_constructed (GObject *object)
 {
   EmpathyCallWindow *self = EMPATHY_CALL_WINDOW (object);
   EmpathyCallWindowPriv *priv = GET_PRIV (self);
-  EmpathyTpCall *call;
+  EmpathyTpStreamedMedia *call;
 
   g_assert (priv->handler != NULL);
 
@@ -1676,7 +1676,7 @@ empathy_call_window_class_init (
 }
 
 static void
-empathy_call_window_video_stream_changed_cb (EmpathyTpCall *call,
+empathy_call_window_video_stream_changed_cb (EmpathyTpStreamedMedia *call,
     GParamSpec *property, EmpathyCallWindow *self)
 {
   DEBUG ("video stream changed");
@@ -1686,7 +1686,7 @@ empathy_call_window_video_stream_changed_cb (EmpathyTpCall *call,
 void
 empathy_call_window_dispose (GObject *object)
 {
-  EmpathyTpCall *call;
+  EmpathyTpStreamedMedia *call;
   EmpathyCallWindow *self = EMPATHY_CALL_WINDOW (object);
   EmpathyCallWindowPriv *priv = GET_PRIV (self);
 
@@ -2267,7 +2267,7 @@ empathy_call_window_update_timer (gpointer user_data)
 
 static void
 display_error (EmpathyCallWindow *self,
-    EmpathyTpCall *call,
+    EmpathyTpStreamedMedia *call,
     const gchar *img,
     const gchar *title,
     const gchar *desc,
@@ -2342,7 +2342,7 @@ display_error (EmpathyCallWindow *self,
 
 static gchar *
 media_stream_error_to_txt (EmpathyCallWindow *self,
-    EmpathyTpCall *call,
+    EmpathyTpStreamedMedia *call,
     gboolean audio,
     TpMediaStreamError error)
 {
@@ -2384,7 +2384,7 @@ media_stream_error_to_txt (EmpathyCallWindow *self,
                 "are not installed on your computer"));
 
       case TP_MEDIA_STREAM_ERROR_INVALID_CM_BEHAVIOR:
-        cm = empathy_tp_call_get_connection_manager (call);
+        cm = empathy_tp_streamed_media_get_connection_manager (call);
 
         url = g_strdup_printf ("http://bugs.freedesktop.org/enter_bug.cgi?"
             "product=Telepathy&amp;component=%s", cm);
@@ -2411,7 +2411,7 @@ media_stream_error_to_txt (EmpathyCallWindow *self,
 
 static void
 empathy_call_window_stream_error (EmpathyCallWindow *self,
-    EmpathyTpCall *call,
+    EmpathyTpStreamedMedia *call,
     gboolean audio,
     guint code,
     const gchar *msg,
@@ -2435,7 +2435,7 @@ empathy_call_window_stream_error (EmpathyCallWindow *self,
 }
 
 static void
-empathy_call_window_audio_stream_error (EmpathyTpCall *call,
+empathy_call_window_audio_stream_error (EmpathyTpStreamedMedia *call,
     guint code,
     const gchar *msg,
     EmpathyCallWindow *self)
@@ -2445,7 +2445,7 @@ empathy_call_window_audio_stream_error (EmpathyTpCall *call,
 }
 
 static void
-empathy_call_window_video_stream_error (EmpathyTpCall *call,
+empathy_call_window_video_stream_error (EmpathyTpStreamedMedia *call,
     guint code,
     const gchar *msg,
     EmpathyCallWindow *self)
@@ -2459,7 +2459,7 @@ empathy_call_window_connected (gpointer user_data)
 {
   EmpathyCallWindow *self = EMPATHY_CALL_WINDOW (user_data);
   EmpathyCallWindowPriv *priv = GET_PRIV (self);
-  EmpathyTpCall *call;
+  EmpathyTpStreamedMedia *call;
   gboolean can_send_video;
 
   empathy_sound_manager_stop (priv->sound_mgr, EMPATHY_SOUND_PHONE_OUTGOING);
@@ -2473,14 +2473,14 @@ empathy_call_window_connected (gpointer user_data)
     G_CALLBACK (empathy_call_window_video_stream_changed_cb),
     self, 0);
 
-  if (empathy_tp_call_has_dtmf (call))
+  if (empathy_tp_streamed_media_has_dtmf (call))
     gtk_widget_set_sensitive (priv->dtmf_panel, TRUE);
 
   if (priv->video_input == NULL)
     empathy_call_window_set_send_video (self, CAMERA_STATE_OFF);
 
   priv->sending_video = can_send_video ?
-    empathy_tp_call_is_sending_video (call) : FALSE;
+    empathy_tp_streamed_media_is_sending_video (call) : FALSE;
 
   gtk_toggle_tool_button_set_active (
       GTK_TOGGLE_TOOL_BUTTON (priv->tool_button_camera_on),
@@ -2795,12 +2795,12 @@ empathy_call_window_bus_message (GstBus *bus, GstMessage *message,
 }
 
 static void
-empathy_call_window_update_avatars_visibility (EmpathyTpCall *call,
+empathy_call_window_update_avatars_visibility (EmpathyTpStreamedMedia *call,
     EmpathyCallWindow *window)
 {
   EmpathyCallWindowPriv *priv = GET_PRIV (window);
 
-  if (empathy_tp_call_is_receiving_video (call))
+  if (empathy_tp_streamed_media_is_receiving_video (call))
     {
       gtk_widget_hide (priv->remote_user_avatar_widget);
       gtk_widget_show (priv->video_output);
@@ -2813,12 +2813,12 @@ empathy_call_window_update_avatars_visibility (EmpathyTpCall *call,
 }
 
 static void
-call_handler_notify_tp_call_cb (EmpathyCallHandler *handler,
+call_handler_notify_tp_streamed_media_cb (EmpathyCallHandler *handler,
     GParamSpec *spec,
     EmpathyCallWindow *self)
 {
   EmpathyCallWindowPriv *priv = GET_PRIV (self);
-  EmpathyTpCall *call;
+  EmpathyTpStreamedMedia *call;
 
   g_object_get (priv->handler, "tp-call", &call, NULL);
   if (call == NULL)
@@ -2836,7 +2836,7 @@ static void
 empathy_call_window_realized_cb (GtkWidget *widget, EmpathyCallWindow *window)
 {
   EmpathyCallWindowPriv *priv = GET_PRIV (window);
-  EmpathyTpCall *call;
+  EmpathyTpStreamedMedia *call;
 
   g_signal_connect (priv->handler, "conference-added",
     G_CALLBACK (empathy_call_window_conference_added_cb), window);
@@ -2868,7 +2868,7 @@ empathy_call_window_realized_cb (GtkWidget *widget, EmpathyCallWindow *window)
       /* tp-call doesn't exist yet, we'll connect signals once it has been
        * set */
       g_signal_connect (priv->handler, "notify::tp-call",
-        G_CALLBACK (call_handler_notify_tp_call_cb), window);
+        G_CALLBACK (call_handler_notify_tp_streamed_media_cb), window);
     }
 
   gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
@@ -3045,7 +3045,7 @@ empathy_call_window_set_send_video (EmpathyCallWindow *window,
   CameraState state)
 {
   EmpathyCallWindowPriv *priv = GET_PRIV (window);
-  EmpathyTpCall *call;
+  EmpathyTpStreamedMedia *call;
 
   priv->sending_video = (state == CAMERA_STATE_ON);
 
@@ -3066,7 +3066,7 @@ empathy_call_window_set_send_video (EmpathyCallWindow *window,
 
   g_object_get (priv->handler, "tp-call", &call, NULL);
   DEBUG ("%s sending video", priv->sending_video ? "start": "stop");
-  empathy_tp_call_request_video_stream_direction (call, priv->sending_video);
+  empathy_tp_streamed_media_request_video_stream_direction (call, priv->sending_video);
   g_object_unref (call);
 }
 
index b20f1719f076c1090c5bd6ededfa9e56a2a65be5..ffe8e597f6881dc97665a69e3dd0121f44fe1afa 100644 (file)
@@ -33,7 +33,7 @@
 #include <libempathy/empathy-tp-contact-factory.h>
 #include <libempathy/empathy-contact-manager.h>
 #include <libempathy/empathy-tp-chat.h>
-#include <libempathy/empathy-tp-call.h>
+#include <libempathy/empathy-tp-streamed-media.h>
 #include <libempathy/empathy-tp-file.h>
 #include <libempathy/empathy-utils.h>
 #include <libempathy/empathy-call-factory.h>
@@ -404,9 +404,9 @@ reject_channel_claim_cb (GObject *source,
       goto out;
     }
 
-  if (EMPATHY_IS_TP_CALL (user_data))
+  if (EMPATHY_IS_TP_STREAMED_MEDIA (user_data))
     {
-      empathy_tp_call_close (user_data);
+      empathy_tp_streamed_media_close (user_data);
     }
   else if (EMPATHY_IS_TP_CHAT (user_data))
     {
@@ -489,7 +489,7 @@ event_channel_process_voip_func (EventPriv *event)
   GtkWidget *dialog;
   GtkWidget *button;
   GtkWidget *image;
-  EmpathyTpCall *call;
+  EmpathyTpStreamedMedia *call;
   gboolean video;
   gchar *title;
 
@@ -499,9 +499,9 @@ event_channel_process_voip_func (EventPriv *event)
       return;
     }
 
-  call = EMPATHY_TP_CALL (event->approval->handler_instance);
+  call = EMPATHY_TP_STREAMED_MEDIA (event->approval->handler_instance);
 
-  video = empathy_tp_call_has_initial_video (call);
+  video = empathy_tp_streamed_media_has_initial_video (call);
 
   dialog = gtk_message_dialog_new (NULL, 0,
       GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
@@ -650,12 +650,12 @@ event_manager_media_channel_got_contact (EventManagerApproval *approval)
   EmpathyEventManagerPriv *priv = GET_PRIV (approval->manager);
   GtkWidget *window = empathy_main_window_dup ();
   gchar *header;
-  EmpathyTpCall *call;
+  EmpathyTpStreamedMedia *call;
   gboolean video;
 
-  call = EMPATHY_TP_CALL (approval->handler_instance);
+  call = EMPATHY_TP_STREAMED_MEDIA (approval->handler_instance);
 
-  video = empathy_tp_call_has_initial_video (call);
+  video = empathy_tp_streamed_media_has_initial_video (call);
 
   header = g_strdup_printf (
     video ? _("Incoming video call from %s") :_("Incoming call from %s"),
@@ -678,7 +678,7 @@ event_manager_media_channel_got_contact (EventManagerApproval *approval)
 }
 
 static void
-event_manager_media_channel_contact_changed_cb (EmpathyTpCall *call,
+event_manager_media_channel_contact_changed_cb (EmpathyTpStreamedMedia *call,
   GParamSpec *param, EventManagerApproval *approval)
 {
   EmpathyContact *contact;
@@ -975,7 +975,7 @@ approve_channels (TpSimpleApprover *approver,
   else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA)
     {
       EmpathyContact *contact;
-      EmpathyTpCall *call = empathy_tp_call_new (account, channel);
+      EmpathyTpStreamedMedia *call = empathy_tp_streamed_media_new (account, channel);
 
       approval->handler_instance = G_OBJECT (call);