[telepathy-gabble/master] Split Hold implementation to a separate source file.

Will Thompson will.thompson at collabora.co.uk
Tue Apr 14 04:11:03 PDT 2009


---
 src/Makefile.am              |    2 +
 src/media-channel-hold.c     |  312 ++++++++++++++++++++++++++++++++++++++++++
 src/media-channel-internal.h |   84 +++++++++++
 src/media-channel.c          |  306 +----------------------------------------
 4 files changed, 403 insertions(+), 301 deletions(-)
 create mode 100644 src/media-channel-hold.c
 create mode 100644 src/media-channel-internal.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 195d687..f550dc4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -72,7 +72,9 @@ libgabble_convenience_la_SOURCES = \
     jingle-transport-iface.h \
     jingle-transport-iface.c \
     media-channel.h \
+    media-channel-internal.h \
     media-channel.c \
+    media-channel-hold.c \
     media-stream.h \
     media-stream.c \
     media-factory.h \
diff --git a/src/media-channel-hold.c b/src/media-channel-hold.c
new file mode 100644
index 0000000..4ee02b1
--- /dev/null
+++ b/src/media-channel-hold.c
@@ -0,0 +1,312 @@
+/*
+ * media-channel-hold.c - Hold and CallState interface implementations
+ * Copyright © 2006–2009 Collabora Ltd.
+ * Copyright © 2006–2009 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "media-channel.h"
+#include "media-channel-internal.h"
+
+#include <telepathy-glib/channel-iface.h>
+
+#define DEBUG_FLAG GABBLE_DEBUG_MEDIA
+
+#include "debug.h"
+#include "util.h"
+
+static void
+inform_peer_of_unhold (GabbleMediaChannel *self)
+{
+  gabble_jingle_session_send_held (self->priv->session, FALSE);
+}
+
+
+static void
+inform_peer_of_hold (GabbleMediaChannel *self)
+{
+  gabble_jingle_session_send_held (self->priv->session, TRUE);
+}
+
+
+static void
+stream_hold_state_changed (GabbleMediaStream *stream G_GNUC_UNUSED,
+    GParamSpec *unused G_GNUC_UNUSED,
+    gpointer data)
+{
+  GabbleMediaChannel *self = data;
+  GabbleMediaChannelPrivate *priv = self->priv;
+  gboolean all_held = TRUE, any_held = FALSE;
+  guint i;
+
+  for (i = 0; i < priv->streams->len; i++)
+    {
+      gboolean its_hold;
+
+      g_object_get (g_ptr_array_index (priv->streams, i),
+          "local-hold", &its_hold,
+          NULL);
+
+      DEBUG ("Stream at index %u has local-hold=%u", i, (guint) its_hold);
+
+      all_held = all_held && its_hold;
+      any_held = any_held || its_hold;
+    }
+
+  DEBUG ("all_held=%u, any_held=%u", (guint) all_held, (guint) any_held);
+
+  if (all_held)
+    {
+      /* Move to state HELD */
+
+      if (priv->hold_state == TP_LOCAL_HOLD_STATE_HELD)
+        {
+          /* nothing changed */
+          return;
+        }
+      else if (priv->hold_state == TP_LOCAL_HOLD_STATE_PENDING_UNHOLD)
+        {
+          /* This can happen if the user asks us to hold, then changes their
+           * mind. We make no particular guarantees about stream states when
+           * in PENDING_UNHOLD state, so keep claiming to be in that state */
+          return;
+        }
+      else if (priv->hold_state == TP_LOCAL_HOLD_STATE_PENDING_HOLD)
+        {
+          /* We wanted to hold, and indeed we have. Yay! Keep whatever
+           * reason code we used for going to PENDING_HOLD */
+          priv->hold_state = TP_LOCAL_HOLD_STATE_HELD;
+        }
+      else
+        {
+          /* We were previously UNHELD. So why have we gone on hold now? */
+          DEBUG ("Unexpectedly entered HELD state!");
+          priv->hold_state = TP_LOCAL_HOLD_STATE_HELD;
+          priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE;
+        }
+    }
+  else if (any_held)
+    {
+      if (priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD)
+        {
+          /* The streaming client has spontaneously changed its stream
+           * state. Why? We just don't know */
+          DEBUG ("Unexpectedly entered PENDING_UNHOLD state!");
+          priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_UNHOLD;
+          priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE;
+        }
+      else if (priv->hold_state == TP_LOCAL_HOLD_STATE_HELD)
+        {
+          /* Likewise */
+          DEBUG ("Unexpectedly entered PENDING_HOLD state!");
+          priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD;
+          priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE;
+        }
+      else
+        {
+          /* nothing particularly interesting - we're trying to change hold
+           * state already, so nothing to signal */
+          return;
+        }
+    }
+  else
+    {
+      /* Move to state UNHELD */
+
+      if (priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD)
+        {
+          /* nothing changed */
+          return;
+        }
+      else if (priv->hold_state == TP_LOCAL_HOLD_STATE_PENDING_HOLD)
+        {
+          /* This can happen if the user asks us to unhold, then changes their
+           * mind. We make no particular guarantees about stream states when
+           * in PENDING_HOLD state, so keep claiming to be in that state */
+          return;
+        }
+      else if (priv->hold_state == TP_LOCAL_HOLD_STATE_PENDING_UNHOLD)
+        {
+          /* We wanted to hold, and indeed we have. Yay! Keep whatever
+           * reason code we used for going to PENDING_UNHOLD */
+          priv->hold_state = TP_LOCAL_HOLD_STATE_UNHELD;
+        }
+      else
+        {
+          /* We were previously HELD. So why have we gone off hold now? */
+          DEBUG ("Unexpectedly entered UNHELD state!");
+          priv->hold_state = TP_LOCAL_HOLD_STATE_UNHELD;
+          priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE;
+        }
+
+      /* Tell the peer what's happened */
+      inform_peer_of_unhold (self);
+    }
+
+  tp_svc_channel_interface_hold_emit_hold_state_changed (self,
+      priv->hold_state, priv->hold_state_reason);
+}
+
+
+static void
+stream_unhold_failed (GabbleMediaStream *stream,
+    gpointer data)
+{
+  GabbleMediaChannel *self = data;
+  GabbleMediaChannelPrivate *priv = self->priv;
+  guint i;
+
+  DEBUG ("%p: %p", self, stream);
+
+  /* Unholding failed - let's roll back to Hold state */
+  priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD;
+  priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_RESOURCE_NOT_AVAILABLE;
+  tp_svc_channel_interface_hold_emit_hold_state_changed (self,
+      priv->hold_state, priv->hold_state_reason);
+
+  /* The stream's state may have changed from unheld to held, so re-poll.
+   * It's possible that all streams are now held, in which case we can stop. */
+  stream_hold_state_changed (stream, NULL, self);
+
+  if (priv->hold_state == TP_LOCAL_HOLD_STATE_HELD)
+    return;
+
+  /* There should be no need to notify the peer, who already thinks they're
+   * on hold, so just tell the streaming client what to do. */
+
+  for (i = 0; i < priv->streams->len; i++)
+    {
+      gabble_media_stream_hold (g_ptr_array_index (priv->streams, i),
+          TRUE);
+    }
+}
+
+
+void
+gabble_media_channel_hold_stream_closed (GabbleMediaChannel *chan,
+    GabbleMediaStream *stream)
+{
+  /* A stream closing might cause the "total" hold state to change:
+   * if there's one held and one unheld, and the unheld one closes,
+   * then our state changes from indeterminate to held. */
+  stream_hold_state_changed (stream, NULL, chan);
+}
+
+
+/* Called by construct_stream to allow the Hold code to hook itself up to a new
+ * stream.
+ */
+void
+gabble_media_channel_hold_new_stream (GabbleMediaChannel *chan,
+    GabbleMediaStream *stream)
+{
+  GObject *chan_o = (GObject *) chan;
+
+  gabble_signal_connect_weak (stream, "unhold-failed",
+      (GCallback) stream_unhold_failed, chan_o);
+  gabble_signal_connect_weak (stream, "notify::local-hold",
+      (GCallback) stream_hold_state_changed, chan_o);
+
+  /* A stream being added might cause the "total" hold state to change */
+  stream_hold_state_changed (stream, NULL, chan);
+}
+
+
+/* Implements RequestHold on Telepathy.Channel.Interface.Hold */
+static void
+gabble_media_channel_request_hold (TpSvcChannelInterfaceHold *iface,
+                                   gboolean hold,
+                                   DBusGMethodInvocation *context)
+{
+  GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface);
+  GabbleMediaChannelPrivate *priv = self->priv;
+  guint i;
+  TpLocalHoldState old_state = priv->hold_state;
+
+  DEBUG ("%p: RequestHold(%u)", self, !!hold);
+
+  if (hold)
+    {
+      if (priv->hold_state == TP_LOCAL_HOLD_STATE_HELD)
+        {
+          DEBUG ("No-op");
+          tp_svc_channel_interface_hold_return_from_request_hold (context);
+          return;
+        }
+
+      if (priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD)
+        {
+          inform_peer_of_hold (self);
+        }
+
+      priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD;
+    }
+  else
+    {
+      if (priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD)
+        {
+          DEBUG ("No-op");
+          tp_svc_channel_interface_hold_return_from_request_hold (context);
+          return;
+        }
+
+      priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_UNHOLD;
+    }
+
+  if (old_state != priv->hold_state ||
+      priv->hold_state_reason != TP_LOCAL_HOLD_STATE_REASON_REQUESTED)
+    {
+      tp_svc_channel_interface_hold_emit_hold_state_changed (self,
+          priv->hold_state, TP_LOCAL_HOLD_STATE_REASON_REQUESTED);
+      priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_REQUESTED;
+    }
+
+  /* Tell streaming client to release or reacquire resources */
+
+  for (i = 0; i < priv->streams->len; i++)
+    {
+      gabble_media_stream_hold (g_ptr_array_index (priv->streams, i), hold);
+    }
+
+  tp_svc_channel_interface_hold_return_from_request_hold (context);
+}
+
+
+/* Implements GetHoldState on Telepathy.Channel.Interface.Hold */
+static void
+gabble_media_channel_get_hold_state (TpSvcChannelInterfaceHold *iface,
+                                     DBusGMethodInvocation *context)
+{
+  GabbleMediaChannel *self = (GabbleMediaChannel *) iface;
+  GabbleMediaChannelPrivate *priv = self->priv;
+
+  tp_svc_channel_interface_hold_return_from_get_hold_state (context,
+      priv->hold_state, priv->hold_state_reason);
+}
+
+
+void
+gabble_media_channel_hold_iface_init (gpointer g_iface,
+    gpointer iface_data G_GNUC_UNUSED)
+{
+  TpSvcChannelInterfaceHoldClass *klass = g_iface;
+
+#define IMPLEMENT(x) tp_svc_channel_interface_hold_implement_##x (\
+    klass, gabble_media_channel_##x)
+  IMPLEMENT(get_hold_state);
+  IMPLEMENT(request_hold);
+#undef IMPLEMENT
+}
diff --git a/src/media-channel-internal.h b/src/media-channel-internal.h
new file mode 100644
index 0000000..d7cd345
--- /dev/null
+++ b/src/media-channel-internal.h
@@ -0,0 +1,84 @@
+/*
+ * media-channel-internal.h - implementation details shared between
+ *                            MediaChannel source files
+ * Copyright © 2006–2009 Collabora Ltd.
+ * Copyright © 2006–2009 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GABBLE_MEDIA_CHANNEL_INTERNAL_H__
+#define __GABBLE_MEDIA_CHANNEL_INTERNAL_H__
+
+#include "media-channel.h"
+
+#include <glib.h>
+
+#include "media-factory.h"
+#include "media-stream.h"
+#include "jingle-session.h"
+#include "jingle-media-rtp.h"
+
+G_BEGIN_DECLS
+
+struct _GabbleMediaChannelPrivate
+{
+  GabbleConnection *conn;
+  gchar *object_path;
+  TpHandle creator;
+  TpHandle initial_peer;
+  gboolean peer_in_rp;
+
+  GabbleMediaFactory *factory;
+  GabbleJingleSession *session;
+
+  /* array of referenced GabbleMediaStream* */
+  GPtrArray *streams;
+  /* list of PendingStreamRequest* in no particular order */
+  GList *pending_stream_requests;
+
+  /* list of StreamCreationData* in no particular order */
+  GList *stream_creation_datas;
+
+  guint next_stream_id;
+
+  TpLocalHoldState hold_state;
+  TpLocalHoldStateReason hold_state_reason;
+
+  /* The "most held" of all associated contents' current states, which is what
+   * we present on CallState.
+   */
+  JingleRtpRemoteState remote_state;
+
+  GPtrArray *delayed_request_streams;
+
+  /* These are really booleans, but gboolean is signed. Thanks, GLib */
+  unsigned ready:1;
+  unsigned closed:1;
+  unsigned dispose_has_run:1;
+};
+
+void gabble_media_channel_hold_new_stream (GabbleMediaChannel *chan,
+    GabbleMediaStream *stream);
+void gabble_media_channel_hold_stream_closed (GabbleMediaChannel *chan,
+    GabbleMediaStream *stream);
+
+void
+gabble_media_channel_hold_iface_init (gpointer g_iface,
+    gpointer iface_data G_GNUC_UNUSED);
+
+G_END_DECLS
+
+#endif /* #ifndef __GABBLE_MEDIA_CHANNEL_INTERNAL_H__ */
diff --git a/src/media-channel.c b/src/media-channel.c
index 529899b..8ec1904 100644
--- a/src/media-channel.c
+++ b/src/media-channel.c
@@ -21,6 +21,7 @@
 
 #include "config.h"
 #include "media-channel.h"
+#include "media-channel-internal.h"
 
 
 #include <dbus/dbus-glib.h>
@@ -52,7 +53,6 @@
 
 static void call_state_iface_init (gpointer, gpointer);
 static void channel_iface_init (gpointer, gpointer);
-static void hold_iface_init (gpointer, gpointer);
 static void media_signalling_iface_init (gpointer, gpointer);
 static void streamed_media_iface_init (gpointer, gpointer);
 static void session_handler_iface_init (gpointer, gpointer);
@@ -65,7 +65,7 @@ G_DEFINE_TYPE_WITH_CODE (GabbleMediaChannel, gabble_media_channel,
     G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP,
       tp_group_mixin_iface_init);
     G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_HOLD,
-      hold_iface_init);
+      gabble_media_channel_hold_iface_init);
     G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_MEDIA_SIGNALLING,
       media_signalling_iface_init);
     G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_STREAMED_MEDIA,
@@ -135,43 +135,6 @@ const TpPropertySignature channel_property_signatures[NUM_CHAN_PROPS] = {
       { "gtalk-p2p-relay-token",  G_TYPE_STRING }
 };
 
-struct _GabbleMediaChannelPrivate
-{
-  GabbleConnection *conn;
-  gchar *object_path;
-  TpHandle creator;
-  TpHandle initial_peer;
-  gboolean peer_in_rp;
-
-  GabbleMediaFactory *factory;
-  GabbleJingleSession *session;
-
-  /* array of referenced GabbleMediaStream* */
-  GPtrArray *streams;
-  /* list of PendingStreamRequest* in no particular order */
-  GList *pending_stream_requests;
-
-  /* list of StreamCreationData* in no particular order */
-  GList *stream_creation_datas;
-
-  guint next_stream_id;
-
-  TpLocalHoldState hold_state;
-  TpLocalHoldStateReason hold_state_reason;
-
-  /* The "most held" of all associated contents' current states, which is what
-   * we present on CallState.
-   */
-  JingleRtpRemoteState remote_state;
-
-  GPtrArray *delayed_request_streams;
-
-  /* These are really booleans, but gboolean is signed. Thanks, GLib */
-  unsigned ready:1;
-  unsigned closed:1;
-  unsigned dispose_has_run:1;
-};
-
 struct _delayed_request_streams_ctx {
   GabbleMediaChannel *chan;
   gulong caps_disco_id;
@@ -2168,174 +2131,6 @@ session_state_changed_cb (GabbleJingleSession *session,
   tp_intset_destroy (set);
 }
 
-
-static void
-inform_peer_of_unhold (GabbleMediaChannel *self)
-{
-  gabble_jingle_session_send_held (self->priv->session, FALSE);
-}
-
-
-static void
-inform_peer_of_hold (GabbleMediaChannel *self)
-{
-  gabble_jingle_session_send_held (self->priv->session, TRUE);
-}
-
-
-static void
-stream_hold_state_changed (GabbleMediaStream *stream G_GNUC_UNUSED,
-                           GParamSpec *unused G_GNUC_UNUSED,
-                           gpointer data)
-{
-  GabbleMediaChannel *self = data;
-  GabbleMediaChannelPrivate *priv = self->priv;
-  gboolean all_held = TRUE, any_held = FALSE;
-  guint i;
-
-  for (i = 0; i < priv->streams->len; i++)
-    {
-      gboolean its_hold;
-
-      g_object_get (g_ptr_array_index (priv->streams, i),
-          "local-hold", &its_hold,
-          NULL);
-
-      DEBUG ("Stream at index %u has local-hold=%u", i, (guint) its_hold);
-
-      all_held = all_held && its_hold;
-      any_held = any_held || its_hold;
-    }
-
-  DEBUG ("all_held=%u, any_held=%u", (guint) all_held, (guint) any_held);
-
-  if (all_held)
-    {
-      /* Move to state HELD */
-
-      if (priv->hold_state == TP_LOCAL_HOLD_STATE_HELD)
-        {
-          /* nothing changed */
-          return;
-        }
-      else if (priv->hold_state == TP_LOCAL_HOLD_STATE_PENDING_UNHOLD)
-        {
-          /* This can happen if the user asks us to hold, then changes their
-           * mind. We make no particular guarantees about stream states when
-           * in PENDING_UNHOLD state, so keep claiming to be in that state */
-          return;
-        }
-      else if (priv->hold_state == TP_LOCAL_HOLD_STATE_PENDING_HOLD)
-        {
-          /* We wanted to hold, and indeed we have. Yay! Keep whatever
-           * reason code we used for going to PENDING_HOLD */
-          priv->hold_state = TP_LOCAL_HOLD_STATE_HELD;
-        }
-      else
-        {
-          /* We were previously UNHELD. So why have we gone on hold now? */
-          DEBUG ("Unexpectedly entered HELD state!");
-          priv->hold_state = TP_LOCAL_HOLD_STATE_HELD;
-          priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE;
-        }
-    }
-  else if (any_held)
-    {
-      if (priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD)
-        {
-          /* The streaming client has spontaneously changed its stream
-           * state. Why? We just don't know */
-          DEBUG ("Unexpectedly entered PENDING_UNHOLD state!");
-          priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_UNHOLD;
-          priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE;
-        }
-      else if (priv->hold_state == TP_LOCAL_HOLD_STATE_HELD)
-        {
-          /* Likewise */
-          DEBUG ("Unexpectedly entered PENDING_HOLD state!");
-          priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD;
-          priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE;
-        }
-      else
-        {
-          /* nothing particularly interesting - we're trying to change hold
-           * state already, so nothing to signal */
-          return;
-        }
-    }
-  else
-    {
-      /* Move to state UNHELD */
-
-      if (priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD)
-        {
-          /* nothing changed */
-          return;
-        }
-      else if (priv->hold_state == TP_LOCAL_HOLD_STATE_PENDING_HOLD)
-        {
-          /* This can happen if the user asks us to unhold, then changes their
-           * mind. We make no particular guarantees about stream states when
-           * in PENDING_HOLD state, so keep claiming to be in that state */
-          return;
-        }
-      else if (priv->hold_state == TP_LOCAL_HOLD_STATE_PENDING_UNHOLD)
-        {
-          /* We wanted to hold, and indeed we have. Yay! Keep whatever
-           * reason code we used for going to PENDING_UNHOLD */
-          priv->hold_state = TP_LOCAL_HOLD_STATE_UNHELD;
-        }
-      else
-        {
-          /* We were previously HELD. So why have we gone off hold now? */
-          DEBUG ("Unexpectedly entered UNHELD state!");
-          priv->hold_state = TP_LOCAL_HOLD_STATE_UNHELD;
-          priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE;
-        }
-
-      /* Tell the peer what's happened */
-      inform_peer_of_unhold (self);
-    }
-
-  tp_svc_channel_interface_hold_emit_hold_state_changed (self,
-      priv->hold_state, priv->hold_state_reason);
-}
-
-
-static void
-stream_unhold_failed (GabbleMediaStream *stream,
-                      gpointer data)
-{
-  GabbleMediaChannel *self = data;
-  GabbleMediaChannelPrivate *priv = self->priv;
-  guint i;
-
-  DEBUG ("%p: %p", self, stream);
-
-  /* Unholding failed - let's roll back to Hold state */
-  priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD;
-  priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_RESOURCE_NOT_AVAILABLE;
-  tp_svc_channel_interface_hold_emit_hold_state_changed (self,
-      priv->hold_state, priv->hold_state_reason);
-
-  /* The stream's state may have changed from unheld to held, so re-poll.
-   * It's possible that all streams are now held, in which case we can stop. */
-  stream_hold_state_changed (stream, NULL, self);
-
-  if (priv->hold_state == TP_LOCAL_HOLD_STATE_HELD)
-    return;
-
-  /* There should be no need to notify the peer, who already thinks they're
-   * on hold, so just tell the streaming client what to do. */
-
-  for (i = 0; i < priv->streams->len; i++)
-    {
-      gabble_media_stream_hold (g_ptr_array_index (priv->streams, i),
-          TRUE);
-    }
-}
-
-
 static void
 stream_close_cb (GabbleMediaStream *stream,
                  GabbleMediaChannel *chan)
@@ -2355,10 +2150,7 @@ stream_close_cb (GabbleMediaStream *stream,
     {
       g_ptr_array_remove (priv->streams, stream);
 
-      /* A stream closing might cause the "total" hold state to change:
-       * if there's one held and one unheld, and the unheld one closes,
-       * then our state changes from indeterminate to held. */
-      stream_hold_state_changed (stream, NULL, chan);
+      gabble_media_channel_hold_stream_closed (chan, stream);
 
       g_object_unref (stream);
     }
@@ -2596,14 +2388,10 @@ construct_stream (GabbleMediaChannel *chan,
       chan_o);
   gabble_signal_connect_weak (stream, "error", (GCallback) stream_error_cb,
       chan_o);
-  gabble_signal_connect_weak (stream, "unhold-failed",
-      (GCallback) stream_unhold_failed, chan_o);
   gabble_signal_connect_weak (stream, "notify::connection-state",
       (GCallback) stream_state_changed_cb, chan_o);
   gabble_signal_connect_weak (stream, "notify::combined-direction",
       (GCallback) stream_direction_changed_cb, chan_o);
-  gabble_signal_connect_weak (stream, "notify::local-hold",
-      (GCallback) stream_hold_state_changed, chan_o);
 
   /* While we're here, watch the active/mute/held state of the corresponding
    * content so we can keep the call state up to date, and call the callback
@@ -2622,13 +2410,12 @@ construct_stream (GabbleMediaChannel *chan,
   tp_svc_channel_type_streamed_media_emit_stream_added (
       chan, id, priv->session->peer, mtype);
 
-  /* A stream being added might cause the "total" hold state to change */
-  stream_hold_state_changed (stream, NULL, chan);
-
   /* Initial stream direction was changed before we had time to hook up
    * signal handler, so we call the handler manually to pick it up. */
   stream_direction_changed_cb (stream, NULL, chan);
 
+  gabble_media_channel_hold_new_stream (chan, stream);
+
   if (priv->ready)
     {
       /* all of the streams are bidirectional from farsight's point of view, it's
@@ -2850,76 +2637,6 @@ gabble_media_channel_get_call_states (TpSvcChannelInterfaceCallState *iface,
 }
 
 static void
-gabble_media_channel_get_hold_state (TpSvcChannelInterfaceHold *iface,
-                                     DBusGMethodInvocation *context)
-{
-  GabbleMediaChannel *self = (GabbleMediaChannel *) iface;
-  GabbleMediaChannelPrivate *priv = self->priv;
-
-  tp_svc_channel_interface_hold_return_from_get_hold_state (context,
-      priv->hold_state, priv->hold_state_reason);
-}
-
-
-static void
-gabble_media_channel_request_hold (TpSvcChannelInterfaceHold *iface,
-                                   gboolean hold,
-                                   DBusGMethodInvocation *context)
-{
-  GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface);
-  GabbleMediaChannelPrivate *priv = self->priv;
-  guint i;
-  TpLocalHoldState old_state = priv->hold_state;
-
-  DEBUG ("%p: RequestHold(%u)", self, !!hold);
-
-  if (hold)
-    {
-      if (priv->hold_state == TP_LOCAL_HOLD_STATE_HELD)
-        {
-          DEBUG ("No-op");
-          tp_svc_channel_interface_hold_return_from_request_hold (context);
-          return;
-        }
-
-      if (priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD)
-        {
-          inform_peer_of_hold (self);
-        }
-
-      priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD;
-    }
-  else
-    {
-      if (priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD)
-        {
-          DEBUG ("No-op");
-          tp_svc_channel_interface_hold_return_from_request_hold (context);
-          return;
-        }
-
-      priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_UNHOLD;
-    }
-
-  if (old_state != priv->hold_state ||
-      priv->hold_state_reason != TP_LOCAL_HOLD_STATE_REASON_REQUESTED)
-    {
-      tp_svc_channel_interface_hold_emit_hold_state_changed (self,
-          priv->hold_state, TP_LOCAL_HOLD_STATE_REASON_REQUESTED);
-      priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_REQUESTED;
-    }
-
-  /* Tell streaming client to release or reacquire resources */
-
-  for (i = 0; i < priv->streams->len; i++)
-    {
-      gabble_media_stream_hold (g_ptr_array_index (priv->streams, i), hold);
-    }
-
-  tp_svc_channel_interface_hold_return_from_request_hold (context);
-}
-
-static void
 _emit_new_stream (GabbleMediaChannel *chan,
                   GabbleMediaStream *stream)
 {
@@ -3073,19 +2790,6 @@ call_state_iface_init (gpointer g_iface,
 }
 
 static void
-hold_iface_init (gpointer g_iface,
-                 gpointer iface_data G_GNUC_UNUSED)
-{
-  TpSvcChannelInterfaceHoldClass *klass = g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_interface_hold_implement_##x (\
-    klass, gabble_media_channel_##x)
-  IMPLEMENT(get_hold_state);
-  IMPLEMENT(request_hold);
-#undef IMPLEMENT
-}
-
-static void
 session_handler_iface_init (gpointer g_iface, gpointer iface_data)
 {
   TpSvcMediaSessionHandlerClass *klass =
-- 
1.5.6.5




More information about the telepathy-commits mailing list