summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Swindell <t.swindell@rubyx.co.uk>2013-04-04 13:08:06 +0000
committerTom Swindell <t.swindell@rubyx.co.uk>2013-04-04 13:08:06 +0000
commit554ca78811f56e91bb2a5941603e05dcaa0233a4 (patch)
treebe527a8ebb712f55152294a1d4ae22da77298a89
parent41a3143837ee5fcabf7959cae1fec17a7a0ff5ae (diff)
Update to new tp base classes and interfaces
Signed-off-by: Tom Swindell <t.swindell@rubyx.co.uk>
-rw-r--r--src/Makefile.am10
-rw-r--r--src/base-call-channel.c754
-rw-r--r--src/base-call-channel.h119
-rw-r--r--src/base-call-content.c434
-rw-r--r--src/base-call-content.h97
-rw-r--r--src/base-call-stream.c351
-rw-r--r--src/base-call-stream.h87
-rw-r--r--src/ring-call-channel.h1
-rw-r--r--src/ring-call-content.c20
-rw-r--r--src/ring-call-content.h11
-rw-r--r--src/ring-call-member.c597
-rw-r--r--src/ring-call-member.h73
-rw-r--r--src/ring-call-stream.c11
-rw-r--r--src/ring-call-stream.h18
-rw-r--r--src/ring-connection.c1
-rw-r--r--src/ring-connection.h5
-rw-r--r--src/ring-util.c1
-rw-r--r--src/ring-util.h2
-rw-r--r--src/util.c525
-rw-r--r--src/util.h110
20 files changed, 1572 insertions, 1655 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 24353ff..d9e1a60 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -42,8 +42,9 @@ test_ring_LDADD = \
libtpring_la_SOURCES = \
base-call-channel.h base-call-channel.c \
- base-call-content.h base-call-content.c \
- base-call-stream.h base-call-stream.c \
+ ring-call-content.h ring-call-content.c \
+ ring-call-stream.h ring-call-stream.c \
+ ring-call-member.h ring-call-member.c \
ring-connection-manager.h ring-connection-manager.c \
ring-protocol.h ring-protocol.c \
ring-connection.h ring-connection.c \
@@ -57,11 +58,10 @@ libtpring_la_SOURCES = \
ring-member-channel.h ring-member-channel.c \
ring-conference-manager.h ring-conference-manager.c \
ring-conference-channel.h ring-conference-channel.c \
- ring-call-content.h ring-call-content.c \
- ring-call-stream.h ring-call-stream.c \
ring-param-spec.h ring-param-spec.c \
ring-emergency-service.h ring-emergency-service.c \
- ring-util.h ring-util.c
+ ring-util.h ring-util.c \
+ util.h util.c
TP_EXTLIB =
TP_EXTLIB += $(top_builddir)/ring-extensions/libtpextensions.a
diff --git a/src/base-call-channel.c b/src/base-call-channel.c
index 9812268..52af824 100644
--- a/src/base-call-channel.c
+++ b/src/base-call-channel.c
@@ -1,7 +1,8 @@
/*
- * base-call-channel.c - Source for GabbleBaseCallChannel
+ * base-call-channel.c - Source for RingBaseCallChannel
* Copyright © 2009–2010 Collabora Ltd.
* @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,189 +19,86 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <gio/gio.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/exportable-channel.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/svc-channel.h>
-#include <telepathy-glib/svc-properties-interface.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
-#include "base-call-channel.h"
-#include "base-call-content.h"
+#include "util.h"
+#include "ring-call-content.h"
+#include "ring-call-member.h"
+#include "base-call-channel.h"
#include "ring-connection.h"
+/*
#define DEBUG_FLAG RING_DEBUG_MEDIA
-#include "ring-debug.h"
+#include "debug.h"
+*/
-static void call_iface_init (gpointer, gpointer);
-static void gabble_base_call_channel_close (TpBaseChannel *base);
+G_DEFINE_TYPE(RingBaseCallChannel, ring_base_call_channel,
+ TP_TYPE_BASE_MEDIA_CALL_CHANNEL);
-G_DEFINE_TYPE_WITH_CODE(GabbleBaseCallChannel, gabble_base_call_channel,
- TP_TYPE_BASE_CHANNEL,
- G_IMPLEMENT_INTERFACE (TP_TYPE_BASE_MEDIA_CALL_CHANNEL,
- call_iface_init)
-);
+static void ring_base_call_channel_hangup (
+ TpBaseCallChannel *base,
+ guint reason,
+ const gchar *detailed_reason,
+ const gchar *message);
-static const gchar *gabble_base_call_channel_interfaces[] = {
- NULL
-};
+static void ring_base_call_channel_close (TpBaseChannel *base);
/* properties */
enum
{
PROP_OBJECT_PATH_PREFIX = 1,
-
- PROP_INITIAL_AUDIO,
- PROP_INITIAL_VIDEO,
- PROP_MUTABLE_CONTENTS,
- PROP_HARDWARE_STREAMING,
- PROP_CONTENTS,
-
- PROP_CALL_STATE,
- PROP_CALL_FLAGS,
- PROP_CALL_STATE_DETAILS,
- PROP_CALL_STATE_REASON,
-
- PROP_CALL_MEMBERS,
-
LAST_PROPERTY
};
-enum
-{
- ENDED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0, };
-
-
/* private structure */
-struct _GabbleBaseCallChannelPrivate
+struct _RingBaseCallChannelPrivate
{
gchar *object_path_prefix;
gboolean dispose_has_run;
- GList *contents;
-
- TpCallState state;
- TpCallFlags flags;
- GHashTable *details;
- GValueArray *reason;
-
- /* handle -> TpCallMemberFlags hash */
+ /* handle -> CallMember object hash */
GHashTable *members;
};
static void
-gabble_base_call_channel_constructed (GObject *obj)
+ring_base_call_channel_init (RingBaseCallChannel *self)
{
- GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (obj);
- TpBaseChannel *base = TP_BASE_CHANNEL (self);
-
- if (G_OBJECT_CLASS (gabble_base_call_channel_parent_class)->constructed
- != NULL)
- G_OBJECT_CLASS (gabble_base_call_channel_parent_class)->constructed (obj);
-
- if (tp_base_channel_is_requested (base))
- gabble_base_call_channel_set_state (self,
- TP_CALL_STATE_PENDING_INITIATOR);
- else
- gabble_base_call_channel_set_state (self,
- TP_CALL_STATE_INITIALISING);
-}
-
-static void
-gabble_base_call_channel_init (GabbleBaseCallChannel *self)
-{
- GabbleBaseCallChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_BASE_CALL_CHANNEL, GabbleBaseCallChannelPrivate);
+ RingBaseCallChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ RING_TYPE_BASE_CALL_CHANNEL, RingBaseCallChannelPrivate);
self->priv = priv;
- priv->reason = tp_value_array_build (3,
- G_TYPE_UINT, 0,
- G_TYPE_UINT, 0,
- G_TYPE_STRING, "",
- G_TYPE_INVALID);
-
- priv->details = tp_asv_new (NULL, NULL);
-
- priv->members = g_hash_table_new (NULL, NULL);
+ priv->members = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, g_object_unref);
}
-static void gabble_base_call_channel_dispose (GObject *object);
-static void gabble_base_call_channel_finalize (GObject *object);
+static void ring_base_call_channel_dispose (GObject *object);
+static void ring_base_call_channel_finalize (GObject *object);
static void
-gabble_base_call_channel_get_property (GObject *object,
+ring_base_call_channel_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
- GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (object);
- GabbleBaseCallChannelPrivate *priv = self->priv;
- GabbleBaseCallChannelClass *klass = GABBLE_BASE_CALL_CHANNEL_GET_CLASS (self);
+ RingBaseCallChannel *self = RING_BASE_CALL_CHANNEL (object);
+ RingBaseCallChannelPrivate *priv = self->priv;
switch (property_id)
{
case PROP_OBJECT_PATH_PREFIX:
g_value_set_string (value, priv->object_path_prefix);
break;
- case PROP_INITIAL_AUDIO:
- g_value_set_boolean (value, self->initial_audio);
- break;
- case PROP_INITIAL_VIDEO:
- g_value_set_boolean (value, self->initial_video);
- break;
- case PROP_MUTABLE_CONTENTS:
- g_value_set_boolean (value, klass->mutable_contents);
- break;
- case PROP_CONTENTS:
- {
- GPtrArray *arr = g_ptr_array_sized_new (2);
- GList *l;
-
- for (l = priv->contents; l != NULL; l = g_list_next (l))
- {
- GabbleBaseCallContent *c = GABBLE_BASE_CALL_CONTENT (l->data);
- g_ptr_array_add (arr,
- (gpointer) gabble_base_call_content_get_object_path (c));
- }
-
- g_value_set_boxed (value, arr);
- g_ptr_array_free (arr, TRUE);
- break;
- }
- case PROP_HARDWARE_STREAMING:
- g_value_set_boolean (value, klass->hardware_streaming);
- break;
- case PROP_CALL_STATE:
- g_value_set_uint (value, priv->state);
- break;
- case PROP_CALL_FLAGS:
- g_value_set_uint (value, priv->flags);
- break;
- case PROP_CALL_STATE_DETAILS:
- g_value_set_boxed (value, priv->details);
- break;
- case PROP_CALL_STATE_REASON:
- g_value_set_boxed (value, priv->reason);
- break;
- case PROP_CALL_MEMBERS:
- g_value_set_boxed (value, priv->members);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -208,25 +106,19 @@ gabble_base_call_channel_get_property (GObject *object,
}
static void
-gabble_base_call_channel_set_property (GObject *object,
+ring_base_call_channel_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
- GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (object);
- GabbleBaseCallChannelPrivate *priv = self->priv;
+ RingBaseCallChannel *self = RING_BASE_CALL_CHANNEL (object);
+ RingBaseCallChannelPrivate *priv = self->priv;
switch (property_id)
{
case PROP_OBJECT_PATH_PREFIX:
priv->object_path_prefix = g_value_dup_string (value);
break;
- case PROP_INITIAL_AUDIO:
- self->initial_audio = g_value_get_boolean (value);
- break;
- case PROP_INITIAL_VIDEO:
- self->initial_video = g_value_get_boolean (value);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -234,10 +126,10 @@ gabble_base_call_channel_set_property (GObject *object,
}
static gchar *
-gabble_base_call_channel_get_object_path_suffix (TpBaseChannel *base)
+ring_base_call_channel_get_object_path_suffix (TpBaseChannel *base)
{
- GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (base);
- GabbleBaseCallChannelPrivate *priv = self->priv;
+ RingBaseCallChannel *self = RING_BASE_CALL_CHANNEL (base);
+ RingBaseCallChannelPrivate *priv = self->priv;
g_assert (priv->object_path_prefix != NULL);
@@ -245,70 +137,30 @@ gabble_base_call_channel_get_object_path_suffix (TpBaseChannel *base)
}
static void
-gabble_base_call_channel_fill_immutable_properties (
- TpBaseChannel *chan,
- GHashTable *properties)
+ring_base_call_channel_class_init (
+ RingBaseCallChannelClass *ring_base_call_channel_class)
{
- TP_BASE_CHANNEL_CLASS (gabble_base_call_channel_parent_class)
- ->fill_immutable_properties (chan, properties);
-
- tp_dbus_properties_mixin_fill_properties_hash (
- G_OBJECT (chan), properties,
- TP_IFACE_CHANNEL_TYPE_CALL, "InitialAudio",
- TP_IFACE_CHANNEL_TYPE_CALL, "InitialVideo",
- TP_IFACE_CHANNEL_TYPE_CALL, "MutableContents",
- TP_IFACE_CHANNEL_TYPE_CALL, "HardwareStreaming",
- NULL);
-}
-
-static void
-gabble_base_call_channel_class_init (
- GabbleBaseCallChannelClass *gabble_base_call_channel_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_base_call_channel_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (ring_base_call_channel_class);
TpBaseChannelClass *base_channel_class =
- TP_BASE_CHANNEL_CLASS (gabble_base_call_channel_class);
+ TP_BASE_CHANNEL_CLASS (ring_base_call_channel_class);
+ TpBaseCallChannelClass *tp_base_call_channel_class =
+ TP_BASE_CALL_CHANNEL_CLASS (ring_base_call_channel_class);
GParamSpec *param_spec;
- static TpDBusPropertiesMixinPropImpl call_props[] = {
- { "CallMembers", "call-members", NULL },
- { "MutableContents", "mutable-contents", NULL },
- { "InitialAudio", "initial-audio", NULL },
- { "InitialVideo", "initial-video", NULL },
- { "Contents", "contents", NULL },
- { "HardwareStreaming", "hardware-streaming", NULL },
- { "CallState", "call-state", NULL },
- { "CallFlags", "call-flags", NULL },
- { "CallStateReason", "call-state-reason", NULL },
- { "CallStateDetails", "call-state-details", NULL },
- { NULL }
- };
-
- g_type_class_add_private (gabble_base_call_channel_class,
- sizeof (GabbleBaseCallChannelPrivate));
-
- object_class->constructed = gabble_base_call_channel_constructed;
-
- object_class->get_property = gabble_base_call_channel_get_property;
- object_class->set_property = gabble_base_call_channel_set_property;
-
- object_class->dispose = gabble_base_call_channel_dispose;
- object_class->finalize = gabble_base_call_channel_finalize;
-
- base_channel_class->channel_type = TP_IFACE_CHANNEL_TYPE_CALL;
- base_channel_class->interfaces = gabble_base_call_channel_interfaces;
+
+ g_type_class_add_private (ring_base_call_channel_class,
+ sizeof (RingBaseCallChannelPrivate));
+
+ object_class->get_property = ring_base_call_channel_get_property;
+ object_class->set_property = ring_base_call_channel_set_property;
+
+ object_class->dispose = ring_base_call_channel_dispose;
+ object_class->finalize = ring_base_call_channel_finalize;
+
base_channel_class->get_object_path_suffix =
- gabble_base_call_channel_get_object_path_suffix;
- base_channel_class->fill_immutable_properties =
- gabble_base_call_channel_fill_immutable_properties;
- base_channel_class->close = gabble_base_call_channel_close;
-
- signals[ENDED] = g_signal_new ("ended",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ ring_base_call_channel_get_object_path_suffix;
+ base_channel_class->close = ring_base_call_channel_close;
+
+ tp_base_call_channel_class->hangup = ring_base_call_channel_hangup;
param_spec = g_param_spec_string ("object-path-prefix", "Object path prefix",
"prefix of the object path",
@@ -316,446 +168,162 @@ gabble_base_call_channel_class_init (
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_OBJECT_PATH_PREFIX,
param_spec);
-
- param_spec = g_param_spec_boolean ("initial-audio", "InitialAudio",
- "Whether the channel initially contained an audio stream",
- FALSE,
- G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIAL_AUDIO,
- param_spec);
-
- param_spec = g_param_spec_boolean ("initial-video", "InitialVideo",
- "Whether the channel initially contained an video stream",
- FALSE,
- G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIAL_VIDEO,
- param_spec);
-
- param_spec = g_param_spec_boolean ("mutable-contents", "MutableContents",
- "Whether the set of streams on this channel are mutable once requested",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_MUTABLE_CONTENTS,
- param_spec);
-
- param_spec = g_param_spec_boxed ("contents", "Contents",
- "The contents of the channel",
- TP_ARRAY_TYPE_OBJECT_PATH_LIST,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CONTENTS,
- param_spec);
-
- param_spec = g_param_spec_boolean ("hardware-streaming", "HardwareStreaming",
- "True if all the streaming is done by hardware",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_HARDWARE_STREAMING,
- param_spec);
-
- param_spec = g_param_spec_uint ("call-state", "CallState",
- "The status of the call",
- TP_CALL_STATE_UNKNOWN,
- NUM_TP_CALL_STATES,
- TP_CALL_STATE_UNKNOWN,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CALL_STATE, param_spec);
-
- param_spec = g_param_spec_uint ("call-flags", "CallFlags",
- "Flags representing the status of the call",
- 0, G_MAXUINT, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CALL_FLAGS,
- param_spec);
-
- param_spec = g_param_spec_boxed ("call-state-reason", "CallStateReason",
- "The reason why the call is in the current state",
- TP_STRUCT_TYPE_CALL_STATE_REASON,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CALL_STATE_REASON,
- param_spec);
-
- param_spec = g_param_spec_boxed ("call-state-details", "CallStateDetails",
- "The reason why the call is in the current state",
- TP_HASH_TYPE_QUALIFIED_PROPERTY_VALUE_MAP,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CALL_STATE_DETAILS,
- param_spec);
-
- param_spec = g_param_spec_boxed ("call-members", "CallMembers",
- "The members",
- TP_HASH_TYPE_CALL_MEMBER_MAP,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CALL_MEMBERS,
- param_spec);
-
- tp_dbus_properties_mixin_implement_interface (object_class,
- TP_IFACE_QUARK_CHANNEL_TYPE_CALL,
- tp_dbus_properties_mixin_getter_gobject_properties,
- NULL,
- call_props);
}
void
-gabble_base_call_channel_dispose (GObject *object)
+ring_base_call_channel_dispose (GObject *object)
{
- GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (object);
- GabbleBaseCallChannelPrivate *priv = self->priv;
+ RingBaseCallChannel *self = RING_BASE_CALL_CHANNEL (object);
+ RingBaseCallChannelPrivate *priv = self->priv;
if (priv->dispose_has_run)
return;
self->priv->dispose_has_run = TRUE;
- g_list_foreach (priv->contents, (GFunc) gabble_base_call_content_deinit, NULL);
- g_list_foreach (priv->contents, (GFunc) g_object_unref, NULL);
- tp_clear_pointer (&priv->contents, g_list_free);
-
tp_clear_pointer (&priv->members, g_hash_table_unref);
- if (G_OBJECT_CLASS (gabble_base_call_channel_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_base_call_channel_parent_class)->dispose (object);
+ if (G_OBJECT_CLASS (ring_base_call_channel_parent_class)->dispose)
+ G_OBJECT_CLASS (ring_base_call_channel_parent_class)->dispose (object);
}
void
-gabble_base_call_channel_finalize (GObject *object)
+ring_base_call_channel_finalize (GObject *object)
{
- GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (object);
- GabbleBaseCallChannelPrivate *priv = self->priv;
+ RingBaseCallChannel *self = RING_BASE_CALL_CHANNEL (object);
+ RingBaseCallChannelPrivate *priv = self->priv;
- g_hash_table_unref (priv->details);
- g_value_array_free (priv->reason);
- g_free (self->priv->object_path_prefix);
+ g_free (priv->object_path_prefix);
- G_OBJECT_CLASS (gabble_base_call_channel_parent_class)->finalize (object);
+ G_OBJECT_CLASS (ring_base_call_channel_parent_class)->finalize (object);
}
-void
-gabble_base_call_channel_set_state (GabbleBaseCallChannel *self,
- TpCallState state)
+RingCallContent *
+ring_base_call_channel_add_content (RingBaseCallChannel *self,
+ const gchar *name,
+ TpCallContentDisposition disposition)
{
- GabbleBaseCallChannelPrivate *priv = self->priv;
-
- DEBUG ("changing from %u to %u", priv->state, state);
-
- if (state == priv->state)
- return;
-
- /* signal when going to the ended state */
- if (state == TP_CALL_STATE_ENDED)
- g_signal_emit (self, signals[ENDED], 0);
-
- priv->state = state;
-
- if (priv->state != TP_CALL_STATE_INITIALISING)
- priv->flags &= ~TP_CALL_FLAG_LOCALLY_RINGING;
-
- if (tp_base_channel_is_registered (TP_BASE_CHANNEL (self)))
- tp_svc_channel_type_call_emit_call_state_changed (self, priv->state,
- priv->flags, priv->reason, priv->details);
-}
-
-TpCallState
-gabble_base_call_channel_get_state (GabbleBaseCallChannel *self)
-{
- return self->priv->state;
-}
-
-void
-gabble_base_call_channel_update_flags (GabbleBaseCallChannel *self,
- TpCallFlags set_flags,
- TpCallFlags clear_flags)
-{
- GabbleBaseCallChannelPrivate *priv = self->priv;
- TpCallFlags old_flags = priv->flags;
-
- priv->flags = (old_flags | set_flags) & ~clear_flags;
- DEBUG ("was %u; set %u and cleared %u; now %u", old_flags, set_flags,
- clear_flags, priv->flags);
-
- if (priv->flags != old_flags)
- tp_svc_channel_type_call_emit_call_state_changed (self, priv->state,
- priv->flags, priv->reason, priv->details);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ gchar *object_path;
+ TpBaseCallContent *content;
+ gchar *escaped;
+
+ /* FIXME could clash when other party in a one-to-one call creates a stream
+ * with the same media type and name */
+ escaped = tp_escape_as_identifier (name);
+ object_path = g_strdup_printf ("%s/Content_%s",
+ tp_base_channel_get_object_path (base),
+ escaped);
+ g_free (escaped);
+
+ content = g_object_new (RING_TYPE_CALL_CONTENT,
+ "connection", tp_base_channel_get_connection (base),
+ "object-path", object_path,
+ "disposition", disposition,
+ //"media-type", wocky_jingle_media_type_to_tp (mtype),
+ "name", name,
+ NULL);
+
+ g_free (object_path);
+
+ tp_base_call_channel_add_content (TP_BASE_CALL_CHANNEL (self),
+ content);
+
+ return RING_CALL_CONTENT (content);
}
-static gboolean
-base_call_channel_update_member (GabbleBaseCallChannel *self,
- TpHandle contact,
- TpCallMemberFlags set_flags,
- TpCallMemberFlags clear_flags,
- TpCallMemberFlags *new_flags)
+static void
+call_member_flags_changed_cb (RingCallMember *member,
+ TpCallMemberFlags flags,
+ gpointer user_data)
{
- gpointer old_flags_p;
-
- DEBUG ("updating member #%u, setting %u and clearing %u", contact, set_flags,
- clear_flags);
-
- if (g_hash_table_lookup_extended (self->priv->members,
- GUINT_TO_POINTER (contact), NULL, &old_flags_p))
- {
- TpCallMemberFlags old_flags = GPOINTER_TO_UINT (old_flags_p);
-
- *new_flags = (old_flags | set_flags) & ~clear_flags;
-
- DEBUG ("previous flags: %u; new flags: %u", old_flags, *new_flags);
-
- if (old_flags == *new_flags)
- return FALSE;
- }
- else
- {
- *new_flags = set_flags & ~clear_flags;
- DEBUG ("not previously a member; new flags: %u", *new_flags);
- }
+ TpBaseCallChannel *base = TP_BASE_CALL_CHANNEL (user_data);
- g_hash_table_insert (self->priv->members, GUINT_TO_POINTER (contact),
- GUINT_TO_POINTER (*new_flags));
- return TRUE;
+ tp_base_call_channel_update_member_flags (base,
+ ring_call_member_get_handle (member),
+ flags,
+ 0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", "");
}
-gboolean
-gabble_base_call_channel_update_members (
- GabbleBaseCallChannel *self,
- TpHandle contact,
- TpCallMemberFlags set_flags,
- TpCallMemberFlags clear_flags,
- ...)
+RingCallMember *
+ring_base_call_channel_get_member_from_handle (
+ RingBaseCallChannel *self,
+ TpHandle handle)
{
- GHashTable *updates = g_hash_table_new (NULL, NULL);
- gboolean updated = FALSE;
- va_list args;
-
- va_start (args, clear_flags);
-
- do
- {
- TpCallMemberFlags new_flags;
-
- if (base_call_channel_update_member (self, contact, set_flags,
- clear_flags, &new_flags))
- {
- g_hash_table_insert (updates,
- GUINT_TO_POINTER (contact),
- GUINT_TO_POINTER (new_flags));
- updated = TRUE;
- }
-
- contact = va_arg (args, TpHandle);
-
- if (contact != 0)
- {
- set_flags = va_arg (args, TpCallMemberFlags);
- clear_flags = va_arg (args, TpCallMemberFlags);
- }
- }
- while (contact != 0);
-
- if (updated)
- {
- GArray *empty = g_array_new (FALSE, FALSE, sizeof (TpHandle));
-
- tp_svc_channel_type_call_emit_call_members_changed (self, updates, NULL,
- empty, empty);
- g_array_unref (empty);
- }
-
- g_hash_table_unref (updates);
- return updated;
+ return g_hash_table_lookup (self->priv->members, GUINT_TO_POINTER (handle));
}
-gboolean
-gabble_base_call_channel_remove_members (
- GabbleBaseCallChannel *self,
- TpHandle contact,
- ...)
+RingCallMember *
+ring_base_call_channel_ensure_member_from_handle (
+ RingBaseCallChannel *self,
+ TpHandle handle)
{
- GArray *removed = g_array_new (FALSE, FALSE, sizeof (TpHandle));
- gboolean updated = FALSE;
- va_list args;
+ RingBaseCallChannelPrivate *priv = self->priv;
+ RingCallMember *m;
- va_start (args, contact);
-
- do
+ m = g_hash_table_lookup (priv->members, GUINT_TO_POINTER (handle));
+ if (m == NULL)
{
- if (g_hash_table_remove (self->priv->members, GUINT_TO_POINTER (contact)))
- {
- g_array_append_val (removed, contact);
- updated = TRUE;
- }
-
- contact = va_arg (args, TpHandle);
- }
- while (contact != 0);
-
- if (updated)
- {
- GHashTable *empty = g_hash_table_new (NULL, NULL);
-
- tp_svc_channel_type_call_emit_call_members_changed (self, empty,
- removed);
- g_hash_table_unref (empty);
+ m = RING_CALL_MEMBER (g_object_new (RING_TYPE_CALL_MEMBER,
+ "target", handle,
+ "call", self,
+ NULL));
+ g_hash_table_insert (priv->members, GUINT_TO_POINTER (handle), m);
+
+ tp_base_call_channel_update_member_flags (TP_BASE_CALL_CHANNEL (self),
+ ring_call_member_get_handle (m),
+ ring_call_member_get_flags (m),
+ 0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", "");
+
+ ring_signal_connect_weak (m, "flags-changed",
+ G_CALLBACK (call_member_flags_changed_cb), G_OBJECT (self));
}
- g_array_unref (removed);
- return updated;
+ return m;
}
void
-gabble_base_call_channel_add_content (GabbleBaseCallChannel *self,
- GabbleBaseCallContent *content)
+ring_base_call_channel_remove_member (RingBaseCallChannel *self,
+ RingCallMember *member)
{
- self->priv->contents = g_list_prepend (self->priv->contents,
- g_object_ref (content));
+ TpHandle h = ring_call_member_get_handle (member);
- if (tp_base_channel_is_registered (TP_BASE_CHANNEL (self)))
- tp_svc_channel_type_call_emit_content_added (self,
- gabble_base_call_content_get_object_path (content),
- gabble_base_call_content_get_media_type (content));
-}
-
-static void
-gabble_base_call_channel_close (TpBaseChannel *base)
-{
- GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (base);
- GabbleBaseCallChannelPrivate *priv = self->priv;
-
- DEBUG ("Closing media channel %s", tp_base_channel_get_object_path (base));
-
- /* shutdown all our contents */
- g_list_foreach (priv->contents, (GFunc) gabble_base_call_content_deinit,
- NULL);
- g_list_foreach (priv->contents, (GFunc) g_object_unref, NULL);
- tp_clear_pointer (&priv->contents, g_list_free);
-
- tp_base_channel_destroyed (base);
-}
-
-static void
-gabble_base_call_channel_ringing (TpSvcChannelTypeCall *iface,
- DBusGMethodInvocation *context)
-{
- GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (iface);
- GabbleBaseCallChannelPrivate *priv = self->priv;
- TpBaseChannel *tp_base = TP_BASE_CHANNEL (self);
+ g_assert (g_hash_table_lookup (self->priv->members,
+ GUINT_TO_POINTER (h))== member);
- if (tp_base_channel_is_requested (tp_base))
- {
- GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Call was requested. Ringing doesn't make sense." };
- dbus_g_method_return_error (context, &e);
- }
- else if (priv->state != TP_CALL_STATE_INITIALISING)
- {
- GError e = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Call is not in the right state for Ringing." };
- dbus_g_method_return_error (context, &e);
- }
- else
- {
- if ((priv->flags & TP_CALL_FLAG_LOCALLY_RINGING) == 0)
- {
- DEBUG ("Client is ringing");
- priv->flags |= TP_CALL_FLAG_LOCALLY_RINGING;
- gabble_base_call_channel_set_state (self, priv->state);
- }
-
- tp_svc_channel_type_call_return_from_ringing (context);
- }
+ ring_call_member_shutdown (member);
+ tp_base_call_channel_remove_member (TP_BASE_CALL_CHANNEL (self),
+ ring_call_member_get_handle (member),
+ 0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", "");
+ g_hash_table_remove (self->priv->members, GUINT_TO_POINTER (h));
}
static void
-gabble_base_call_channel_accept (TpSvcChannelTypeCall *iface,
- DBusGMethodInvocation *context)
+ring_base_call_channel_shutdown_all_members (RingBaseCallChannel *self)
{
- GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (iface);
- GabbleBaseCallChannelPrivate *priv = self->priv;
- GabbleBaseCallChannelClass *base_class =
- GABBLE_BASE_CALL_CHANNEL_GET_CLASS (self);
- TpBaseChannel *tp_base = TP_BASE_CHANNEL (self);
-
- DEBUG ("Client accepted the call");
+ GHashTableIter iter;
+ gpointer value;
- if (tp_base_channel_is_requested (tp_base))
- {
- if (priv->state == TP_CALL_STATE_PENDING_INITIATOR)
- {
- gabble_base_call_channel_set_state (self,
- TP_CALL_STATE_INITIALISING);
- }
- else
- {
- DEBUG ("Invalid state for Accept: Channel requested and "
- "state == %d", priv->state);
- goto err;
- }
- }
- else if (priv->state < TP_CALL_STATE_ACCEPTED)
- {
- gabble_base_call_channel_set_state (self,
- TP_CALL_STATE_ACCEPTED);
- }
- else
- {
- DEBUG ("Invalid state for Accept: state == %d", priv->state);
- goto err;
- }
-
- if (base_class->accept != NULL)
- base_class->accept (self);
-
- tp_svc_channel_type_call_return_from_accept (context);
- return;
-
-err:
- {
- GError e = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Invalid state for Accept" };
- dbus_g_method_return_error (context, &e);
- }
+ g_hash_table_iter_init (&iter, self->priv->members);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ ring_call_member_shutdown (RING_CALL_MEMBER (value));
}
static void
-gabble_base_call_channel_hangup (TpSvcChannelTypeCall *iface,
- guint reason,
- const gchar *detailed_reason,
- const gchar *message,
- DBusGMethodInvocation *context)
+ring_base_call_channel_hangup (TpBaseCallChannel *base,
+ guint reason,
+ const gchar *detailed_reason,
+ const gchar *message)
{
- GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (iface);
- GabbleBaseCallChannelClass *base_class =
- GABBLE_BASE_CALL_CHANNEL_GET_CLASS (self);
-
- if (base_class->hangup)
- base_class->hangup (self, reason, detailed_reason, message);
-
- gabble_base_call_channel_set_state ( GABBLE_BASE_CALL_CHANNEL (self),
- TP_CALL_STATE_ENDED);
-
- tp_svc_channel_type_call_return_from_hangup (context);
+ ring_base_call_channel_shutdown_all_members (
+ RING_BASE_CALL_CHANNEL (base));
}
static void
-gabble_base_call_channel_add_content_dbus (RingSvcChannelTypeCall *iface,
- const gchar *name,
- TpMediaStreamType mtype,
- DBusGMethodInvocation *context)
+ring_base_call_channel_close (TpBaseChannel *base)
{
- GError e = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
- "Contents cannot be added; only a single audio content is supported" };
+ ring_base_call_channel_shutdown_all_members (
+ RING_BASE_CALL_CHANNEL (base));
- dbus_g_method_return_error (context, &e);
-}
-
-
-static void
-call_iface_init (gpointer g_iface, gpointer iface_data)
-{
- RingSvcChannelTypeCallClass *klass = g_iface;
-
-#define IMPLEMENT(x, suffix) ring_svc_channel_type_call_implement_##x (\
- klass, gabble_base_call_channel_##x##suffix)
- IMPLEMENT(ringing,);
- IMPLEMENT(accept,);
- IMPLEMENT(hangup,);
- IMPLEMENT(add_content, _dbus);
-#undef IMPLEMENT
+ TP_BASE_CHANNEL_CLASS (ring_base_call_channel_parent_class)->close (base);
}
diff --git a/src/base-call-channel.h b/src/base-call-channel.h
index c82fe90..0660f98 100644
--- a/src/base-call-channel.h
+++ b/src/base-call-channel.h
@@ -1,7 +1,8 @@
/*
- * base-call-channel.h - Header for GabbleBaseCallChannel
+ * base-call-channel.h - Header for RingBaseCallChannel
* Copyright © 2009–2010 Collabora Ltd.
* @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,87 +19,77 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef __GABBLE_BASE_CALL_CHANNEL_H__
-#define __GABBLE_BASE_CALL_CHANNEL_H__
+#ifndef __RING_BASE_CALL_CHANNEL_H__
+#define __RING_BASE_CALL_CHANNEL_H__
#include <glib-object.h>
-#include <ring-extensions/ring-extensions.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
-#include <telepathy-glib/base-channel.h>
-
-#include "base-call-content.h"
+#include "ring-call-content.h"
+#include "ring-call-member.h"
G_BEGIN_DECLS
-typedef struct _GabbleBaseCallChannel GabbleBaseCallChannel;
-typedef struct _GabbleBaseCallChannelPrivate GabbleBaseCallChannelPrivate;
-typedef struct _GabbleBaseCallChannelClass GabbleBaseCallChannelClass;
-
-struct _GabbleBaseCallChannelClass {
- TpBaseChannelClass parent_class;
-
- gboolean hardware_streaming;
- gboolean mutable_contents;
+typedef struct _RingBaseCallChannel RingBaseCallChannel;
+typedef struct _RingBaseCallChannelPrivate RingBaseCallChannelPrivate;
+typedef struct _RingBaseCallChannelClass RingBaseCallChannelClass;
- void (*accept) (GabbleBaseCallChannel *self);
- void (*hangup) (GabbleBaseCallChannel *self,
- guint reason,
- const gchar *detailed_reason,
- const gchar *message);
+struct _RingBaseCallChannelClass {
+ TpBaseMediaCallChannelClass parent_class;
};
-struct _GabbleBaseCallChannel {
- TpBaseChannel parent;
+struct _RingBaseCallChannel {
+ TpBaseMediaCallChannel parent;
- gboolean initial_audio;
- gboolean initial_video;
-
- GabbleBaseCallChannelPrivate *priv;
+ RingBaseCallChannelPrivate *priv;
};
-GType gabble_base_call_channel_get_type (void);
+GType ring_base_call_channel_get_type (void);
/* TYPE MACROS */
-#define GABBLE_TYPE_BASE_CALL_CHANNEL \
- (gabble_base_call_channel_get_type ())
-#define GABBLE_BASE_CALL_CHANNEL(obj) \
+#define RING_TYPE_BASE_CALL_CHANNEL \
+ (ring_base_call_channel_get_type ())
+#define RING_BASE_CALL_CHANNEL(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
- GABBLE_TYPE_BASE_CALL_CHANNEL, GabbleBaseCallChannel))
-#define GABBLE_BASE_CALL_CHANNEL_CLASS(klass) \
+ RING_TYPE_BASE_CALL_CHANNEL, RingBaseCallChannel))
+#define RING_BASE_CALL_CHANNEL_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), \
- GABBLE_TYPE_BASE_CALL_CHANNEL, GabbleBaseCallChannelClass))
-#define GABBLE_IS_BASE_CALL_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_BASE_CALL_CHANNEL))
-#define GABBLE_IS_BASE_CALL_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_BASE_CALL_CHANNEL))
-#define GABBLE_BASE_CALL_CHANNEL_GET_CLASS(obj) \
+ RING_TYPE_BASE_CALL_CHANNEL, RingBaseCallChannelClass))
+#define RING_IS_BASE_CALL_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), RING_TYPE_BASE_CALL_CHANNEL))
+#define RING_IS_BASE_CALL_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), RING_TYPE_BASE_CALL_CHANNEL))
+#define RING_BASE_CALL_CHANNEL_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
- GABBLE_TYPE_BASE_CALL_CHANNEL, GabbleBaseCallChannelClass))
-
-TpCallState gabble_base_call_channel_get_state (
- GabbleBaseCallChannel *self);
-void gabble_base_call_channel_set_state (GabbleBaseCallChannel *self,
- TpCallState state);
-
-void gabble_base_call_channel_update_flags (GabbleBaseCallChannel *self,
- TpCallFlags set_flags,
- TpCallFlags clear_flags);
-
-gboolean gabble_base_call_channel_update_members (
- GabbleBaseCallChannel *self,
- TpHandle contact,
- TpCallMemberFlags set_flags,
- TpCallMemberFlags clear_flags,
- ...) G_GNUC_NULL_TERMINATED;
-gboolean gabble_base_call_channel_remove_members (
- GabbleBaseCallChannel *self,
- TpHandle contact,
- ...) G_GNUC_NULL_TERMINATED;
-
-void gabble_base_call_channel_add_content (GabbleBaseCallChannel *self,
- GabbleBaseCallContent *content);
+ RING_TYPE_BASE_CALL_CHANNEL, RingBaseCallChannelClass))
+
+RingCallMember *ring_base_call_channel_ensure_member (
+ RingBaseCallChannel *self,
+ const gchar *jid);
+
+void ring_base_call_channel_remove_member (RingBaseCallChannel *self,
+ RingCallMember *member);
+
+RingCallMember *ring_base_call_channel_ensure_member_from_handle (
+ RingBaseCallChannel *self,
+ TpHandle handle);
+
+RingCallMember * ring_base_call_channel_get_member_from_handle (
+ RingBaseCallChannel *self,
+ TpHandle handle);
+
+RingCallContent * ring_base_call_channel_add_content (
+ RingBaseCallChannel *self,
+ const gchar *name,
+ TpCallContentDisposition disposition);
+
+void ring_base_call_channel_remove_content (RingBaseCallChannel *self,
+ RingCallContent *content);
+
+GHashTable *ring_base_call_channel_get_members (RingBaseCallChannel *self);
G_END_DECLS
-#endif /* #ifndef __GABBLE_BASE_CALL_CHANNEL_H__*/
+#endif /* #ifndef __RING_BASE_CALL_CHANNEL_H__*/
diff --git a/src/base-call-content.c b/src/base-call-content.c
deleted file mode 100644
index 44fb532..0000000
--- a/src/base-call-content.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * base-call-content.c - Source for GabbleBaseCallContent
- * Copyright © 2009–2010 Collabora Ltd.
- * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
- * @author Will Thompson <will.thompson@collabora.co.uk>
- *
- * 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 "base-call-content.h"
-
-#include "base-call-stream.h"
-
-#define DEBUG_FLAG RING_DEBUG_MEDIA
-#include "ring-debug.h"
-
-G_DEFINE_TYPE_WITH_CODE(GabbleBaseCallContent, gabble_base_call_content,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
- tp_dbus_properties_mixin_iface_init);
- /* The base class doesn't implement Remove(), which is pretty
- * protocol-specific. It just implements the properties.
- */
- G_IMPLEMENT_INTERFACE (RING_TYPE_SVC_CALL_CONTENT,
- NULL);
- );
-
-struct _GabbleBaseCallContentPrivate
-{
- RingConnection *conn;
- TpDBusDaemon *dbus_daemon;
-
- gchar *object_path;
-
- gchar *name;
- TpMediaStreamType media_type;
- TpHandle creator;
- TpCallContentDisposition disposition;
-
- GList *streams;
-
- gboolean dispose_has_run;
- gboolean deinit_has_run;
-};
-
-enum
-{
- PROP_OBJECT_PATH = 1,
- PROP_CONNECTION,
-
- PROP_INTERFACES,
- PROP_NAME,
- PROP_MEDIA_TYPE,
- PROP_CREATOR,
- PROP_DISPOSITION,
- PROP_STREAMS
-};
-
-static void base_call_content_deinit_real (GabbleBaseCallContent *self);
-
-static void
-gabble_base_call_content_init (GabbleBaseCallContent *self)
-{
- GabbleBaseCallContentPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_BASE_CALL_CONTENT, GabbleBaseCallContentPrivate);
-
- self->priv = priv;
-}
-
-static void
-gabble_base_call_content_constructed (GObject *obj)
-{
- GabbleBaseCallContent *self = GABBLE_BASE_CALL_CONTENT (obj);
- GabbleBaseCallContentPrivate *priv = self->priv;
-
- if (G_OBJECT_CLASS (gabble_base_call_content_parent_class)->constructed != NULL)
- G_OBJECT_CLASS (gabble_base_call_content_parent_class)->constructed (obj);
-
- DEBUG ("Registering %s", priv->object_path);
- priv->dbus_daemon = g_object_ref (
- tp_base_connection_get_dbus_daemon ((TpBaseConnection *) priv->conn));
- tp_dbus_daemon_register_object (priv->dbus_daemon, priv->object_path, obj);
-}
-
-static void
-gabble_base_call_content_dispose (GObject *object)
-{
- GabbleBaseCallContent *self = GABBLE_BASE_CALL_CONTENT (object);
- GabbleBaseCallContentPrivate *priv = self->priv;
- GList *l;
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- for (l = priv->streams; l != NULL; l = g_list_next (l))
- g_object_unref (l->data);
-
- tp_clear_pointer (&priv->streams, g_list_free);
- tp_clear_object (&priv->conn);
-
- if (G_OBJECT_CLASS (gabble_base_call_content_parent_class)->dispose != NULL)
- G_OBJECT_CLASS (gabble_base_call_content_parent_class)->dispose (object);
-}
-
-static void
-gabble_base_call_content_finalize (GObject *object)
-{
- GabbleBaseCallContent *self = GABBLE_BASE_CALL_CONTENT (object);
- GabbleBaseCallContentPrivate *priv = self->priv;
-
- /* free any data held directly by the object here */
- g_free (priv->object_path);
- g_free (priv->name);
-
- G_OBJECT_CLASS (gabble_base_call_content_parent_class)->finalize (object);
-}
-
-static void
-gabble_base_call_content_get_property (
- GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleBaseCallContent *content = GABBLE_BASE_CALL_CONTENT (object);
- GabbleBaseCallContentPrivate *priv = content->priv;
-
- switch (property_id)
- {
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- case PROP_INTERFACES:
- {
- GabbleBaseCallContentClass *klass =
- GABBLE_BASE_CALL_CONTENT_GET_CLASS (content);
-
- if (klass->extra_interfaces != NULL)
- {
- g_value_set_boxed (value, klass->extra_interfaces);
- }
- else
- {
- static gchar *empty[] = { NULL };
-
- g_value_set_boxed (value, empty);
- }
- break;
- }
- case PROP_NAME:
- g_value_set_string (value, priv->name);
- break;
- case PROP_MEDIA_TYPE:
- g_value_set_uint (value, priv->media_type);
- break;
- case PROP_CREATOR:
- g_value_set_uint (value, priv->creator);
- break;
- case PROP_DISPOSITION:
- g_value_set_uint (value, priv->disposition);
- break;
- case PROP_STREAMS:
- {
- GPtrArray *arr = g_ptr_array_sized_new (2);
- GList *l;
-
- for (l = priv->streams; l != NULL; l = g_list_next (l))
- {
- GabbleBaseCallStream *s = GABBLE_BASE_CALL_STREAM (l->data);
- g_ptr_array_add (arr,
- g_strdup (gabble_base_call_stream_get_object_path (s)));
- }
-
- g_value_take_boxed (value, arr);
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_base_call_content_set_property (
- GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleBaseCallContent *content = GABBLE_BASE_CALL_CONTENT (object);
- GabbleBaseCallContentPrivate *priv = content->priv;
-
- switch (property_id)
- {
- case PROP_OBJECT_PATH:
- priv->object_path = g_value_dup_string (value);
- g_assert (priv->object_path != NULL);
- break;
- case PROP_CONNECTION:
- priv->conn = g_value_dup_object (value);
- break;
- case PROP_NAME:
- priv->name = g_value_dup_string (value);
- break;
- case PROP_MEDIA_TYPE:
- priv->media_type = g_value_get_uint (value);
- break;
- case PROP_CREATOR:
- priv->creator = g_value_get_uint (value);
- break;
- case PROP_DISPOSITION:
- priv->disposition = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_base_call_content_class_init (
- GabbleBaseCallContentClass *bcc_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (bcc_class);
- GParamSpec *param_spec;
- static TpDBusPropertiesMixinPropImpl content_props[] = {
- { "Interfaces", "interfaces", NULL },
- { "Name", "name", NULL },
- { "Type", "media-type", NULL },
- { "Creator", "creator", NULL },
- { "Disposition", "disposition", NULL },
- { "Streams", "streams", NULL },
- { NULL }
- };
- static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
- { RING_IFACE_CALL_CONTENT,
- tp_dbus_properties_mixin_getter_gobject_properties,
- NULL,
- content_props,
- },
- { NULL }
- };
-
- g_type_class_add_private (bcc_class, sizeof (GabbleBaseCallContentPrivate));
-
- object_class->constructed = gabble_base_call_content_constructed;
- object_class->dispose = gabble_base_call_content_dispose;
- object_class->finalize = gabble_base_call_content_finalize;
- object_class->get_property = gabble_base_call_content_get_property;
- object_class->set_property = gabble_base_call_content_set_property;
-
- param_spec = g_param_spec_string ("object-path", "D-Bus object path",
- "The D-Bus object path used for this object on the bus.",
- NULL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_OBJECT_PATH, param_spec);
-
- param_spec = g_param_spec_object ("connection", "RingConnection object",
- "Gabble connection object that owns this call content",
- RING_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
- "Additional interfaces implemented by this content",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
-
- param_spec = g_param_spec_string ("name", "Name",
- "The name of this content, if any",
- "",
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_NAME, param_spec);
-
- param_spec = g_param_spec_uint ("media-type", "Media Type",
- "The media type of this content",
- 0, G_MAXUINT, 0,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_MEDIA_TYPE, param_spec);
-
- param_spec = g_param_spec_uint ("creator", "Creator",
- "The creator of this content",
- 0, G_MAXUINT, 0,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CREATOR, param_spec);
-
- param_spec = g_param_spec_uint ("disposition", "Disposition",
- "The disposition of this content",
- 0, G_MAXUINT, 0,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_DISPOSITION, param_spec);
-
- param_spec = g_param_spec_boxed ("streams", "Stream",
- "The streams of this content",
- TP_ARRAY_TYPE_OBJECT_PATH_LIST,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_STREAMS,
- param_spec);
-
- bcc_class->dbus_props_class.interfaces = prop_interfaces;
- tp_dbus_properties_mixin_class_init (object_class,
- G_STRUCT_OFFSET (GabbleBaseCallContentClass, dbus_props_class));
-
- bcc_class->deinit = base_call_content_deinit_real;
-}
-
-RingConnection *
-gabble_base_call_content_get_connection (GabbleBaseCallContent *self)
-{
- g_return_val_if_fail (GABBLE_IS_BASE_CALL_CONTENT (self), NULL);
-
- return self->priv->conn;
-}
-
-const gchar *
-gabble_base_call_content_get_object_path (GabbleBaseCallContent *self)
-{
- g_return_val_if_fail (GABBLE_IS_BASE_CALL_CONTENT (self), NULL);
-
- return self->priv->object_path;
-}
-
-const gchar *
-gabble_base_call_content_get_name (GabbleBaseCallContent *self)
-{
- g_return_val_if_fail (GABBLE_IS_BASE_CALL_CONTENT (self), NULL);
-
- return self->priv->name;
-}
-
-TpMediaStreamType
-gabble_base_call_content_get_media_type (GabbleBaseCallContent *self)
-{
- g_return_val_if_fail (GABBLE_IS_BASE_CALL_CONTENT (self),
- TP_MEDIA_STREAM_TYPE_AUDIO);
-
- return self->priv->media_type;
-}
-
-TpCallContentDisposition
-gabble_base_call_content_get_disposition (GabbleBaseCallContent *self)
-{
- g_return_val_if_fail (GABBLE_IS_BASE_CALL_CONTENT (self),
- TP_CALL_CONTENT_DISPOSITION_NONE);
-
- return self->priv->disposition;
-}
-
-GList *
-gabble_base_call_content_get_streams (GabbleBaseCallContent *self)
-{
- g_return_val_if_fail (GABBLE_IS_BASE_CALL_CONTENT (self), NULL);
-
- return self->priv->streams;
-}
-
-void
-gabble_base_call_content_add_stream (GabbleBaseCallContent *self,
- GabbleBaseCallStream *stream)
-{
- g_return_if_fail (GABBLE_IS_BASE_CALL_CONTENT (self));
-
- self->priv->streams = g_list_prepend (self->priv->streams,
- g_object_ref (stream));
- ring_svc_call_content_emit_stream_added (self,
- gabble_base_call_stream_get_object_path (stream));
-}
-
-void
-gabble_base_call_content_remove_stream (GabbleBaseCallContent *self,
- GabbleBaseCallStream *stream)
-{
- GabbleBaseCallContentPrivate *priv;
- GList *l;
-
- g_return_if_fail (GABBLE_IS_BASE_CALL_CONTENT (self));
-
- priv = self->priv;
-
- l = g_list_find (priv->streams, stream);
- g_return_if_fail (l != NULL);
-
- priv->streams = g_list_remove_link (priv->streams, l);
- ring_svc_call_content_emit_stream_removed (self,
- gabble_base_call_stream_get_object_path (stream));
- g_object_unref (stream);
-}
-
-static void
-base_call_content_deinit_real (GabbleBaseCallContent *self)
-{
- GabbleBaseCallContentPrivate *priv = self->priv;
-
- if (priv->deinit_has_run)
- return;
-
- priv->deinit_has_run = TRUE;
-
- tp_dbus_daemon_unregister_object (priv->dbus_daemon, G_OBJECT (self));
- tp_clear_object (&priv->dbus_daemon);
-
- g_list_foreach (priv->streams, (GFunc) g_object_unref, NULL);
- tp_clear_pointer (&priv->streams, g_list_free);
-}
-
-void
-gabble_base_call_content_deinit (GabbleBaseCallContent *self)
-{
- GabbleBaseCallContentClass *klass;
-
- g_return_if_fail (GABBLE_IS_BASE_CALL_CONTENT (self));
-
- klass = GABBLE_BASE_CALL_CONTENT_GET_CLASS (self);
- g_return_if_fail (klass->deinit != NULL);
- klass->deinit (self);
-}
diff --git a/src/base-call-content.h b/src/base-call-content.h
deleted file mode 100644
index 705f7b1..0000000
--- a/src/base-call-content.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * base-call-content.h - Header for GabbleBaseBaseCallContent
- * Copyright © 2009–2010 Collabora Ltd.
- * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
- * @author Will Thompson <will.thompson@collabora.co.uk>
- *
- * 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_BASE_CALL_CONTENT_H
-#define GABBLE_BASE_CALL_CONTENT_H
-
-#include <glib-object.h>
-
-#include <telepathy-glib/telepathy-glib.h>
-
-#include <ring-extensions/ring-extensions.h>
-
-#include "ring-connection.h"
-#include "base-call-stream.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleBaseCallContent GabbleBaseCallContent;
-typedef struct _GabbleBaseCallContentPrivate GabbleBaseCallContentPrivate;
-typedef struct _GabbleBaseCallContentClass GabbleBaseCallContentClass;
-
-typedef void (*GabbleBaseCallContentFunc) (GabbleBaseCallContent *);
-
-struct _GabbleBaseCallContentClass {
- GObjectClass parent_class;
-
- TpDBusPropertiesMixinClass dbus_props_class;
-
- const gchar * const *extra_interfaces;
- GabbleBaseCallContentFunc deinit;
-};
-
-struct _GabbleBaseCallContent {
- GObject parent;
-
- GabbleBaseCallContentPrivate *priv;
-};
-
-GType gabble_base_call_content_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_BASE_CALL_CONTENT \
- (gabble_base_call_content_get_type ())
-#define GABBLE_BASE_CALL_CONTENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), \
- GABBLE_TYPE_BASE_CALL_CONTENT, GabbleBaseCallContent))
-#define GABBLE_BASE_CALL_CONTENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), \
- GABBLE_TYPE_BASE_CALL_CONTENT, GabbleBaseCallContentClass))
-#define GABBLE_IS_BASE_CALL_CONTENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_BASE_CALL_CONTENT))
-#define GABBLE_IS_BASE_CALL_CONTENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_BASE_CALL_CONTENT))
-#define GABBLE_BASE_CALL_CONTENT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), \
- GABBLE_TYPE_BASE_CALL_CONTENT, GabbleBaseCallContentClass))
-
-RingConnection *gabble_base_call_content_get_connection (
- GabbleBaseCallContent *self);
-const gchar *gabble_base_call_content_get_object_path (
- GabbleBaseCallContent *self);
-
-const gchar *gabble_base_call_content_get_name (GabbleBaseCallContent *self);
-TpMediaStreamType gabble_base_call_content_get_media_type (
- GabbleBaseCallContent *self);
-TpCallContentDisposition gabble_base_call_content_get_disposition (
- GabbleBaseCallContent *self);
-
-GList *gabble_base_call_content_get_streams (GabbleBaseCallContent *self);
-void gabble_base_call_content_add_stream (GabbleBaseCallContent *self,
- GabbleBaseCallStream *stream);
-void gabble_base_call_content_remove_stream (GabbleBaseCallContent *self,
- GabbleBaseCallStream *stream);
-
-void gabble_base_call_content_deinit (GabbleBaseCallContent *self);
-
-G_END_DECLS
-
-#endif /* #ifndef __GABBLE_BASE_CALL_CONTENT_H__*/
diff --git a/src/base-call-stream.c b/src/base-call-stream.c
deleted file mode 100644
index e8449aa..0000000
--- a/src/base-call-stream.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * base-call-stream.c - Source for GabbleBaseCallStream
- * Copyright © 2009–2010 Collabora Ltd.
- * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
- * @author Will Thompson <will.thompson@collabora.co.uk>
- *
- * 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 "base-call-stream.h"
-
-#define DEBUG_FLAG RING_DEBUG_MEDIA
-#include "ring-debug.h"
-
-#include "ring-connection.h"
-
-G_DEFINE_TYPE_WITH_CODE(GabbleBaseCallStream, gabble_base_call_stream,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
- tp_dbus_properties_mixin_iface_init);
- /* The base class doesn't implement SetSending or RequestReceiving, because
- * they're pretty protocol-specific. It just implements the properties. */
- G_IMPLEMENT_INTERFACE (RING_TYPE_SVC_CALL_STREAM, NULL);
- )
-
-enum
-{
- PROP_OBJECT_PATH = 1,
- PROP_CONNECTION,
-
- /* Call interface properties */
- PROP_INTERFACES,
- PROP_SENDERS,
-};
-
-struct _GabbleBaseCallStreamPrivate
-{
- gboolean dispose_has_run;
-
- gchar *object_path;
- RingConnection *conn;
-
- GHashTable *senders;
-};
-
-static void
-gabble_base_call_stream_init (GabbleBaseCallStream *self)
-{
- GabbleBaseCallStreamPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_BASE_CALL_STREAM, GabbleBaseCallStreamPrivate);
-
- self->priv = priv;
- priv->senders = g_hash_table_new (g_direct_hash, g_direct_equal);
-}
-
-static void
-gabble_base_call_stream_constructed (GObject *obj)
-{
- GabbleBaseCallStream *self = GABBLE_BASE_CALL_STREAM (obj);
- GabbleBaseCallStreamPrivate *priv = self->priv;
- TpDBusDaemon *bus = tp_base_connection_get_dbus_daemon (
- (TpBaseConnection *) priv->conn);
-
- if (G_OBJECT_CLASS (gabble_base_call_stream_parent_class)->constructed
- != NULL)
- G_OBJECT_CLASS (gabble_base_call_stream_parent_class)->constructed (obj);
-
- DEBUG ("Registering %s", priv->object_path);
- tp_dbus_daemon_register_object (bus, priv->object_path, obj);
-}
-
-static void
-gabble_base_call_stream_dispose (GObject *object)
-{
- GabbleBaseCallStream *self = GABBLE_BASE_CALL_STREAM (object);
- GabbleBaseCallStreamPrivate *priv = self->priv;
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- tp_clear_object (&priv->conn);
-
- if (G_OBJECT_CLASS (gabble_base_call_stream_parent_class)->dispose != NULL)
- G_OBJECT_CLASS (gabble_base_call_stream_parent_class)->dispose (object);
-}
-
-static void
-gabble_base_call_stream_finalize (GObject *object)
-{
- GabbleBaseCallStream *self = GABBLE_BASE_CALL_STREAM (object);
- GabbleBaseCallStreamPrivate *priv = self->priv;
-
- /* free any data held directly by the object here */
- g_free (priv->object_path);
- g_hash_table_destroy (priv->senders);
-
- if (G_OBJECT_CLASS (gabble_base_call_stream_parent_class)->finalize != NULL)
- G_OBJECT_CLASS (gabble_base_call_stream_parent_class)->finalize (object);
-}
-
-static void
-gabble_base_call_stream_get_property (
- GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleBaseCallStream *self = GABBLE_BASE_CALL_STREAM (object);
- GabbleBaseCallStreamPrivate *priv = self->priv;
-
- switch (property_id)
- {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_INTERFACES:
- {
- GabbleBaseCallStreamClass *klass =
- GABBLE_BASE_CALL_STREAM_GET_CLASS (self);
-
- if (klass->extra_interfaces != NULL)
- {
- g_value_set_boxed (value, klass->extra_interfaces);
- }
- else
- {
- gchar *empty[] = { NULL };
-
- g_value_set_boxed (value, empty);
- }
- break;
- }
- case PROP_SENDERS:
- g_value_set_boxed (value, priv->senders);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_base_call_stream_set_property (
- GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleBaseCallStream *self = GABBLE_BASE_CALL_STREAM (object);
- GabbleBaseCallStreamPrivate *priv = self->priv;
-
- switch (property_id)
- {
- case PROP_CONNECTION:
- priv->conn = g_value_dup_object (value);
- g_assert (priv->conn != NULL);
- break;
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_base_call_stream_class_init (GabbleBaseCallStreamClass *bsc_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (bsc_class);
- GParamSpec *param_spec;
- static TpDBusPropertiesMixinPropImpl stream_props[] = {
- { "Interfaces", "interfaces", NULL },
- { "Senders", "senders", NULL },
- { NULL }
- };
- static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
- { RING_IFACE_CALL_STREAM,
- tp_dbus_properties_mixin_getter_gobject_properties,
- NULL,
- stream_props,
- },
- { NULL }
- };
-
- g_type_class_add_private (bsc_class, sizeof (GabbleBaseCallStreamPrivate));
-
- object_class->constructed = gabble_base_call_stream_constructed;
- object_class->dispose = gabble_base_call_stream_dispose;
- object_class->finalize = gabble_base_call_stream_finalize;
- object_class->set_property = gabble_base_call_stream_set_property;
- object_class->get_property = gabble_base_call_stream_get_property;
-
- param_spec = g_param_spec_string ("object-path", "D-Bus object path",
- "The D-Bus object path used for this object on the bus.",
- NULL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_OBJECT_PATH, param_spec);
-
- param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
- "Additional interfaces implemented by this stream",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
-
- param_spec = g_param_spec_boxed ("senders", "Senders",
- "Sender map",
- RING_HASH_TYPE_CONTACT_SENDING_STATE_MAP,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_SENDERS, param_spec);
-
- param_spec = g_param_spec_object ("connection", "RingConnection object",
- "Gabble connection object that owns this call stream",
- RING_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- bsc_class->dbus_props_class.interfaces = prop_interfaces;
- tp_dbus_properties_mixin_class_init (object_class,
- G_STRUCT_OFFSET (GabbleBaseCallStreamClass, dbus_props_class));
-}
-
-RingConnection *
-gabble_base_call_stream_get_connection (GabbleBaseCallStream *self)
-{
- g_return_val_if_fail (GABBLE_IS_BASE_CALL_STREAM (self), NULL);
-
- return self->priv->conn;
-}
-
-const gchar *
-gabble_base_call_stream_get_object_path (GabbleBaseCallStream *self)
-{
- g_return_val_if_fail (GABBLE_IS_BASE_CALL_STREAM (self), NULL);
-
- return self->priv->object_path;
-}
-
-static gboolean
-base_call_stream_sender_update_state (GabbleBaseCallStream *self,
- TpHandle contact,
- TpSendingState state)
-{
- GabbleBaseCallStreamPrivate *priv = self->priv;
- gpointer state_p = 0;
- gboolean exists;
-
- exists = g_hash_table_lookup_extended (priv->senders,
- GUINT_TO_POINTER (contact),
- NULL,
- &state_p);
-
- if (exists && GPOINTER_TO_UINT (state_p) == state)
- return FALSE;
-
- DEBUG ("Updating sender %d state: %d => %d", contact,
- GPOINTER_TO_UINT (state_p), state);
-
- g_hash_table_insert (priv->senders,
- GUINT_TO_POINTER (contact),
- GUINT_TO_POINTER (state));
-
- return TRUE;
-}
-
-gboolean
-gabble_base_call_stream_update_senders (
- GabbleBaseCallStream *self,
- TpHandle contact,
- TpSendingState state,
- ...)
-{
- GHashTable *updates = g_hash_table_new (g_direct_hash, g_direct_equal);
- gboolean updated = FALSE;
- va_list args;
-
- va_start (args, state);
-
- do
- {
- if (base_call_stream_sender_update_state (self, contact, state))
- {
- g_hash_table_insert (updates,
- GUINT_TO_POINTER (contact),
- GUINT_TO_POINTER (state));
- updated = TRUE;
- }
-
- contact = va_arg (args, TpHandle);
- if (contact != 0)
- state = va_arg (args, TpSendingState);
- }
- while (contact != 0);
-
- if (updated)
- {
- GArray *empty = g_array_new (FALSE, TRUE, sizeof (TpHandle));
-
- ring_svc_call_stream_emit_senders_changed (self, updates, empty);
- g_array_unref (empty);
- }
-
- g_hash_table_unref (updates);
- return updated;
-}
-
-TpSendingState
-gabble_base_call_stream_get_sender_state (
- GabbleBaseCallStream *self,
- TpHandle sender,
- gboolean *existed)
-{
- gpointer state;
-
- g_return_val_if_fail (GABBLE_IS_BASE_CALL_STREAM (self),
- TP_SENDING_STATE_NONE);
-
- if (g_hash_table_lookup_extended (self->priv->senders,
- GUINT_TO_POINTER (sender), NULL, &state))
- {
- if (existed != NULL)
- *existed = TRUE;
-
- return GPOINTER_TO_UINT (state);
- }
- else
- {
- if (existed != NULL)
- *existed = FALSE;
-
- return TP_SENDING_STATE_NONE;
- }
-}
diff --git a/src/base-call-stream.h b/src/base-call-stream.h
deleted file mode 100644
index b33ef7c..0000000
--- a/src/base-call-stream.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * base-call-stream.h - Header for GabbleBaseCallStream
- * Copyright © 2009–2010 Collabora Ltd.
- * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
- * @author Will Thompson <will.thompson@collabora.co.uk>
- *
- * 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_BASE_CALL_STREAM_H
-#define GABBLE_BASE_CALL_STREAM_H
-
-#include <glib-object.h>
-
-#include <telepathy-glib/telepathy-glib.h>
-#include <ring-extensions/ring-extensions.h>
-
-#include "ring-connection.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GabbleBaseCallStream GabbleBaseCallStream;
-typedef struct _GabbleBaseCallStreamPrivate GabbleBaseCallStreamPrivate;
-typedef struct _GabbleBaseCallStreamClass GabbleBaseCallStreamClass;
-
-struct _GabbleBaseCallStreamClass {
- GObjectClass parent_class;
-
- TpDBusPropertiesMixinClass dbus_props_class;
-
- const gchar * const *extra_interfaces;
-};
-
-struct _GabbleBaseCallStream {
- GObject parent;
-
- GabbleBaseCallStreamPrivate *priv;
-};
-
-GType gabble_base_call_stream_get_type (void);
-
-/* TYPE MACROS */
-#define GABBLE_TYPE_BASE_CALL_STREAM \
- (gabble_base_call_stream_get_type ())
-#define GABBLE_BASE_CALL_STREAM(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_BASE_CALL_STREAM, GabbleBaseCallStream))
-#define GABBLE_BASE_CALL_STREAM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_BASE_CALL_STREAM, \
- GabbleBaseCallStreamClass))
-#define GABBLE_IS_BASE_CALL_STREAM(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_BASE_CALL_STREAM))
-#define GABBLE_IS_BASE_CALL_STREAM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_BASE_CALL_STREAM))
-#define GABBLE_BASE_CALL_STREAM_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_BASE_CALL_STREAM, \
- GabbleBaseCallStreamClass))
-
-RingConnection *gabble_base_call_stream_get_connection (
- GabbleBaseCallStream *self);
-const gchar *gabble_base_call_stream_get_object_path (
- GabbleBaseCallStream *self);
-
-TpSendingState gabble_base_call_stream_get_sender_state (
- GabbleBaseCallStream *self,
- TpHandle sender,
- gboolean *existed);
-gboolean gabble_base_call_stream_update_senders (
- GabbleBaseCallStream *self,
- TpHandle contact,
- TpSendingState state,
- ...) G_GNUC_NULL_TERMINATED;
-
-G_END_DECLS
-
-#endif
diff --git a/src/ring-call-channel.h b/src/ring-call-channel.h
index 8813a97..f2e1067 100644
--- a/src/ring-call-channel.h
+++ b/src/ring-call-channel.h
@@ -3,6 +3,7 @@
*
* Copyright (C) 2007-2009 Nokia Corporation
* @author Pekka Pessi <first.surname@nokia.com>
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
*
* This work is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/src/ring-call-content.c b/src/ring-call-content.c
index 30cc802..3837eb9 100644
--- a/src/ring-call-content.c
+++ b/src/ring-call-content.c
@@ -3,6 +3,7 @@
* Copyright ©2010 Collabora Ltd.
* Copyright ©2010 Nokia Corporation
* @author Will Thompson <will.thompson@collabora.co.uk>
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -35,10 +36,8 @@ struct _RingCallContentPrivate {
static void implement_call_content (gpointer klass,
gpointer unused G_GNUC_UNUSED);
-G_DEFINE_TYPE_WITH_CODE (RingCallContent, ring_call_content,
- GABBLE_TYPE_BASE_CALL_CONTENT,
- G_IMPLEMENT_INTERFACE (RING_TYPE_SVC_CALL_CONTENT, implement_call_content);
-)
+G_DEFINE_TYPE (RingCallContent, ring_call_content,
+ TP_TYPE_BASE_MEDIA_CALL_CONTENT);
static void
ring_call_content_init (RingCallContent *self)
@@ -52,18 +51,18 @@ ring_call_content_constructed (GObject *object)
{
RingCallContent *self = RING_CALL_CONTENT (object);
RingCallContentPrivate *priv = self->priv;
- GabbleBaseCallContent *base = GABBLE_BASE_CALL_CONTENT (self);
+ TpBaseCallContent *base = TP_BASE_CALL_CONTENT (self);
gchar *stream_path;
if (G_OBJECT_CLASS (ring_call_content_parent_class)->constructed != NULL)
G_OBJECT_CLASS (ring_call_content_parent_class)->constructed (object);
stream_path = g_strdup_printf ("%s/%s",
- gabble_base_call_content_get_object_path (base), "stream");
+ tp_base_call_content_get_object_path (base), "stream");
priv->stream = ring_call_stream_new (
- gabble_base_call_content_get_connection (base), stream_path);
- gabble_base_call_content_add_stream (base,
- GABBLE_BASE_CALL_STREAM (priv->stream));
+ RING_CONNECTION(tp_base_call_content_get_connection (base)), stream_path);
+ tp_base_call_content_add_stream (base,
+ TP_BASE_CALL_STREAM (priv->stream));
g_free (stream_path);
}
@@ -83,6 +82,7 @@ static void
ring_call_content_class_init (RingCallContentClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ TpBaseCallContentClass *base_class = TP_BASE_CALL_CONTENT_CLASS(klass);
object_class->constructed = ring_call_content_constructed;
object_class->dispose = ring_call_content_dispose;
@@ -115,7 +115,7 @@ ring_call_content_get_stream (RingCallContent *self)
static void
ring_call_content_remove (
- RingSvcCallContent *self,
+ RingCallContent *self,
DBusGMethodInvocation *context)
{
/* We could just leave all this out — the base class leaves Remove()
diff --git a/src/ring-call-content.h b/src/ring-call-content.h
index a33a4be..f6cc737 100644
--- a/src/ring-call-content.h
+++ b/src/ring-call-content.h
@@ -3,6 +3,7 @@
* Copyright ©2010 Collabora Ltd.
* Copyright ©2010 Nokia Corporation
* @author Will Thompson <will.thompson@collabora.co.uk>
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,7 +25,9 @@
#include <glib-object.h>
-#include "base-call-content.h"
+#include <telepathy-glib/telepathy-glib.h>
+
+#include "ring-connection.h"
#include "ring-call-stream.h"
typedef struct _RingCallContent RingCallContent;
@@ -32,11 +35,11 @@ typedef struct _RingCallContentClass RingCallContentClass;
typedef struct _RingCallContentPrivate RingCallContentPrivate;
struct _RingCallContentClass {
- GabbleBaseCallContentClass parent_class;
+ TpBaseMediaCallContentClass parent_class;
};
struct _RingCallContent {
- GabbleBaseCallContent parent;
+ TpBaseMediaCallContent parent;
RingCallContentPrivate *priv;
};
@@ -49,6 +52,8 @@ RingCallContent *ring_call_content_new (RingConnection *connection,
RingCallStream *ring_call_content_get_stream (RingCallContent *self);
+static void ring_call_content_remove(RingCallContent *self, DBusGMethodInvocation *context);
+
/* TYPE MACROS */
#define RING_TYPE_CALL_CONTENT \
(ring_call_content_get_type ())
diff --git a/src/ring-call-member.c b/src/ring-call-member.c
new file mode 100644
index 0000000..8a3bb39
--- /dev/null
+++ b/src/ring-call-member.c
@@ -0,0 +1,597 @@
+/*
+ * ring-call-member.c - Source for CallMember
+ * Copyright (C) 2010 Collabora Ltd.
+ * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+
+#include "base-call-channel.h"
+
+#include "ring-connection.h"
+#include "ring-call-member.h"
+
+G_DEFINE_TYPE(RingCallMember, ring_call_member, G_TYPE_OBJECT)
+
+/* signal enum */
+enum
+{
+ FLAGS_CHANGED,
+ CONTENT_ADDED,
+ CONTENT_REMOVED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/* properties */
+enum
+{
+ PROP_CALL = 1,
+ PROP_TARGET
+};
+
+/* private structure */
+struct _RingCallMemberPrivate
+{
+ TpHandle target;
+
+ RingBaseCallChannel *call;
+ TpCallMemberFlags flags;
+
+ GList *contents;
+ gchar *transport_ns;
+ gboolean accepted;
+
+ gboolean dispose_has_run;
+};
+
+#define RING_CALL_MEMBER_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), RING_TYPE_CALL_MEMBER, \
+ RingCallMemberPrivate))
+
+static void
+ring_call_member_init (RingCallMember *self)
+{
+ RingCallMemberPrivate *priv =
+ RING_CALL_MEMBER_GET_PRIVATE (self);
+
+ self->priv = priv;
+ priv->accepted = FALSE;
+}
+
+static void
+ring_call_member_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ RingCallMember *self = RING_CALL_MEMBER (object);
+ RingCallMemberPrivate *priv = self->priv;
+
+ switch (property_id)
+ {
+ case PROP_CALL:
+ g_value_set_object (value, ring_call_member_get_connection (self));
+ break;
+ case PROP_TARGET:
+ g_value_set_uint (value, priv->target);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+ring_call_member_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ RingCallMember *self = RING_CALL_MEMBER (object);
+ RingCallMemberPrivate *priv = self->priv;
+
+ switch (property_id)
+ {
+ case PROP_CALL:
+ priv->call = g_value_get_object (value);
+ g_assert (priv->call != NULL);
+ break;
+ case PROP_TARGET:
+ priv->target = g_value_get_uint (value);
+ g_assert (priv->target != 0);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void ring_call_member_dispose (GObject *object);
+static void ring_call_member_finalize (GObject *object);
+
+static void
+ring_call_member_class_init (
+ RingCallMemberClass *ring_call_member_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (ring_call_member_class);
+ GParamSpec *param_spec;
+
+ g_type_class_add_private (ring_call_member_class,
+ sizeof (RingCallMemberPrivate));
+
+ object_class->dispose = ring_call_member_dispose;
+ object_class->finalize = ring_call_member_finalize;
+
+ object_class->get_property = ring_call_member_get_property;
+ object_class->set_property = ring_call_member_set_property;
+
+ param_spec = g_param_spec_object ("call", "Call",
+ "The base call object that contains this member",
+ RING_TYPE_BASE_CALL_CHANNEL,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CALL, param_spec);
+
+ param_spec = g_param_spec_uint ("target", "Target",
+ "the target handle of member",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_TARGET, param_spec);
+
+ signals[FLAGS_CHANGED] =
+ g_signal_new ("flags-changed",
+ G_OBJECT_CLASS_TYPE (ring_call_member_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+
+ signals[CONTENT_ADDED] =
+ g_signal_new ("content-added",
+ G_OBJECT_CLASS_TYPE (ring_call_member_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+ signals[CONTENT_REMOVED] =
+ g_signal_new ("content-removed",
+ G_OBJECT_CLASS_TYPE (ring_call_member_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
+}
+
+void
+ring_call_member_dispose (GObject *object)
+{
+ RingCallMember *self = RING_CALL_MEMBER (object);
+ RingCallMemberPrivate *priv = self->priv;
+ GList *l;
+
+ if (priv->dispose_has_run)
+ return;
+
+ priv->dispose_has_run = TRUE;
+
+ for (l = priv->contents ; l != NULL; l = g_list_next (l))
+ g_object_unref (l->data);
+
+ tp_clear_pointer (&priv->contents, g_list_free);
+
+ /* release any references held by the object here */
+
+ if (G_OBJECT_CLASS (ring_call_member_parent_class)->dispose)
+ G_OBJECT_CLASS (ring_call_member_parent_class)->dispose (object);
+}
+
+void
+ring_call_member_finalize (GObject *object)
+{
+ RingCallMember *self = RING_CALL_MEMBER (object);
+ RingCallMemberPrivate *priv = self->priv;
+
+ g_free (priv->transport_ns);
+ priv->transport_ns = NULL;
+
+ G_OBJECT_CLASS (ring_call_member_parent_class)->finalize (object);
+}
+
+/*
+static void
+remote_state_changed_cb (WockyJingleSession *session, gpointer user_data)
+{
+ RingCallMember *self = RING_CALL_MEMBER (user_data);
+ RingCallMemberPrivate *priv = self->priv;
+ TpCallMemberFlags newflags = 0;
+
+ if (wocky_jingle_session_get_remote_ringing (session))
+ newflags |= TP_CALL_MEMBER_FLAG_RINGING;
+
+ if (wocky_jingle_session_get_remote_hold (session))
+ newflags |= TP_CALL_MEMBER_FLAG_HELD;
+
+ if (priv->flags == newflags)
+ return;
+
+ priv->flags = newflags;
+
+ DEBUG ("Call members flags changed to: %d", priv->flags);
+
+ g_signal_emit (self, signals[FLAGS_CHANGED], 0, priv->flags);
+}
+*/
+
+/*
+static void
+member_content_removed_cb (RingCallMemberContent *mcontent,
+ gpointer user_data)
+{
+ RingCallMember *self = RING_CALL_MEMBER (user_data);
+ RingCallMemberPrivate *priv = self->priv;
+
+ priv->contents = g_list_remove (priv->contents, mcontent);
+ g_signal_emit (self, signals[CONTENT_REMOVED], 0, mcontent);
+ g_object_unref (mcontent);
+}
+
+static void
+ring_call_member_add_member_content (RingCallMember *self,
+ RingCallMemberContent *content)
+{
+ RingCallMemberPrivate *priv = self->priv;
+
+ priv->contents = g_list_prepend (priv->contents, content);
+
+ ring_signal_connect_weak (content, "removed",
+ G_CALLBACK (member_content_removed_cb), G_OBJECT (self));
+
+ g_signal_emit (self, signals[CONTENT_ADDED], 0, content);
+}
+*/
+
+/* This function handles additional contents added by the remote side */
+/*
+static void
+new_content_cb (WockyJingleSession *session,
+ WockyJingleContent *c,
+ gpointer user_data)
+{
+ RingCallMember *self = RING_CALL_MEMBER (user_data);
+ RingCallMemberContent *content = NULL;
+
+ if (wocky_jingle_content_is_created_by_us (c))
+ return;
+
+ content = ring_call_member_content_from_jingle_content (c, self);
+
+ ring_call_member_add_member_content (self, content);
+}
+
+static gboolean
+call_member_update_existing_content (RingCallMember *self,
+ WockyJingleContent *content)
+{
+ GList *l;
+
+ for (l = self->priv->contents; l != NULL ; l = g_list_next (l))
+ {
+ RingCallMemberContent *mcontent = RING_CALL_MEMBER_CONTENT (l->data);
+
+ if (ring_call_member_content_has_jingle_content (mcontent))
+ continue;
+
+ if (!tp_strdiff (ring_call_member_content_get_name (mcontent),
+ wocky_jingle_content_get_name (content)))
+ {
+ ring_call_member_content_set_jingle_content (mcontent, content);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void
+ring_call_member_set_session (RingCallMember *self,
+ WockyJingleSession *session)
+{
+ RingCallMemberPrivate *priv = self->priv;
+ GList *c, *contents;
+
+ g_assert (priv->session == NULL);
+ g_assert (session != NULL);
+
+ DEBUG ("Setting session: %p -> %p\n", self, session);
+ priv->session = g_object_ref (session);
+
+ contents = wocky_jingle_session_get_contents (session);
+ for (c = contents ; c != NULL; c = g_list_next (c))
+ {
+ WockyJingleContent *content = WOCKY_JINGLE_CONTENT (c->data);
+
+ if (priv->transport_ns == NULL)
+ {
+ g_object_get (content, "transport-ns",
+ &priv->transport_ns,
+ NULL);
+ }
+
+ if (!call_member_update_existing_content (self, content))
+ {
+ RingCallMemberContent *mcontent =
+ ring_call_member_content_from_jingle_content (content,
+ self);
+
+ ring_call_member_add_member_content (self, mcontent);
+ }
+ }
+
+ g_object_notify (G_OBJECT (self), "session");
+
+ ring_signal_connect_weak (priv->session, "remote-state-changed",
+ G_CALLBACK (remote_state_changed_cb), G_OBJECT (self));
+ ring_signal_connect_weak (priv->session, "new-content",
+ G_CALLBACK (new_content_cb), G_OBJECT (self));
+
+ if (priv->accepted)
+ ring_call_member_accept (self);
+
+ g_list_free (contents);
+}
+
+WockyJingleSession *
+ring_call_member_get_session (RingCallMember *self)
+{
+ return self->priv->session;
+}
+*/
+
+TpCallMemberFlags
+ring_call_member_get_flags (RingCallMember *self)
+{
+ return self->priv->flags;
+}
+
+TpHandle ring_call_member_get_handle (
+ RingCallMember *self)
+{
+ return self->priv->target;
+}
+
+GList *
+ring_call_member_get_contents (RingCallMember *self)
+{
+ RingCallMemberPrivate *priv = self->priv;
+
+ return priv->contents;
+}
+
+/*
+RingCallMemberContent *
+ring_call_member_ensure_content (RingCallMember *self,
+ const gchar *name,
+ WockyJingleMediaType mtype)
+{
+ RingCallMemberPrivate *priv = self->priv;
+ GList *l;
+ RingCallMemberContent *content = NULL;
+
+ for (l = priv->contents ; l != NULL; l = g_list_next (l))
+ {
+ RingCallMemberContent *c = RING_CALL_MEMBER_CONTENT (l->data);
+
+ if (ring_call_member_content_get_media_type (c) == mtype &&
+ !tp_strdiff (ring_call_member_content_get_name (c), name))
+ {
+ content = c;
+ break;
+ }
+ }
+
+ if (content == NULL)
+ {
+ content = ring_call_member_content_new (name, mtype, self);
+ ring_call_member_add_member_content (self, content);
+ }
+
+ return content;
+}
+
+RingCallMemberContent *
+ring_call_member_create_content (RingCallMember *self,
+ const gchar *name,
+ WockyJingleMediaType mtype,
+ WockyJingleContentSenders senders,
+ GError **error)
+{
+ RingCallMemberPrivate *priv = self->priv;
+ const gchar *content_ns;
+ WockyJingleContent *c;
+ RingCallMemberContent *content;
+ const gchar *peer_resource;
+
+ g_assert (priv->session != NULL);
+
+ peer_resource = wocky_jingle_session_get_peer_resource (priv->session);
+
+ DEBUG ("Creating new content %s, type %d", name, mtype);
+
+ if (peer_resource != NULL)
+ DEBUG ("existing call, using peer resource %s", peer_resource);
+ else
+ DEBUG ("existing call, using bare JID");
+
+ content_ns = jingle_pick_best_content_type (ring_call_member_get_connection (self),
+ priv->target,
+ peer_resource, mtype);
+
+ if (content_ns == NULL)
+ {
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
+ "Content type %d not available for this resource", mtype);
+ return NULL;
+ }
+
+ DEBUG ("Creating new jingle content with ns %s : %s",
+ content_ns, priv->transport_ns);
+
+ c = wocky_jingle_session_add_content (priv->session,
+ mtype, senders, name, content_ns, priv->transport_ns);
+
+ g_assert (c != NULL);
+
+ content = ring_call_member_content_from_jingle_content (c, self);
+
+ ring_call_member_add_member_content (self, content);
+
+ return content;
+}
+
+void
+ring_call_member_accept (RingCallMember *self)
+{
+ self->priv->accepted = TRUE;
+
+ if (self->priv->session != NULL)
+ wocky_jingle_session_accept (self->priv->session);
+}
+*/
+
+/**
+ * Start a new session using the existing contents for this member. For now
+ * assumes we're using the latest jingle dialect and ice-udp
+ * FIXME: make dialect and transport selection more dynamic?
+ */
+/*
+gboolean
+ring_call_member_open_session (RingCallMember *self,
+ GError **error)
+{
+ RingCallMemberPrivate *priv = self->priv;
+ RingConnection *conn = ring_call_member_get_connection (self);
+ WockyJingleFactory *jf;
+ WockyJingleSession *session;
+ gchar *jid;
+
+ jid = ring_peer_to_jid (conn, priv->target, NULL);
+
+ jf = ring_jingle_mint_get_factory (conn->jingle_mint);
+ g_return_val_if_fail (jf != NULL, FALSE);
+
+ session = wocky_jingle_factory_create_session (jf, jid, WOCKY_JINGLE_DIALECT_V032,
+ FALSE);
+ DEBUG ("Created a jingle session: %p", session);
+
+ priv->transport_ns = g_strdup (NS_JINGLE_TRANSPORT_ICEUDP);
+
+ ring_call_member_set_session (self, session);
+
+ g_free (jid);
+
+ return TRUE;
+}
+
+gboolean
+ring_call_member_start_session (RingCallMember *self,
+ const gchar *audio_name,
+ const gchar *video_name,
+ GError **error)
+{
+ RingCallMemberPrivate *priv = self->priv;
+ TpBaseChannel *base_channel = TP_BASE_CHANNEL (priv->call);
+ TpHandle target = tp_base_channel_get_target_handle (base_channel);
+ const gchar *resource;
+ WockyJingleDialect dialect;
+ gchar *jid;
+ const gchar *transport;
+ WockyJingleFactory *jf;
+ WockyJingleSession *session;
+
+ // FIXME might need to wait on capabilities, also don't need transport
+ // and dialect already
+ if (!jingle_pick_best_resource (ring_call_member_get_connection (self),
+ target, audio_name != NULL, video_name != NULL,
+ &transport, &dialect, &resource))
+ {
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE,
+ "member does not have the desired audio/video capabilities");
+ return FALSE;
+ }
+
+ jid = ring_peer_to_jid (ring_call_member_get_connection (self), target, resource);
+
+ jf = ring_jingle_mint_get_factory (
+ ring_call_member_get_connection (self)->jingle_mint);
+ g_return_val_if_fail (jf != NULL, FALSE);
+
+ session = wocky_jingle_factory_create_session (jf, jid, dialect, FALSE);
+ g_free (jid);
+
+ ring_call_member_set_session (self, session);
+
+ priv->transport_ns = g_strdup (transport);
+
+ if (audio_name != NULL)
+ ring_call_member_create_content (self, audio_name,
+ WOCKY_JINGLE_MEDIA_TYPE_AUDIO, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, NULL);
+
+ if (video_name != NULL)
+ ring_call_member_create_content (self, video_name,
+ WOCKY_JINGLE_MEDIA_TYPE_VIDEO, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, NULL);
+
+ return TRUE;
+}
+*/
+
+RingConnection *
+ring_call_member_get_connection (RingCallMember *self)
+{
+ TpBaseChannel *base_chan = TP_BASE_CHANNEL (self->priv->call);
+
+ return RING_CONNECTION (tp_base_channel_get_connection (base_chan));
+}
+
+const gchar *
+ring_call_member_get_transport_ns (RingCallMember *self)
+{
+ return self->priv->transport_ns;
+}
+
+void
+ring_call_member_shutdown (RingCallMember *self)
+{
+ RingCallMemberPrivate *priv = self->priv;
+
+ /* removing the content will remove it from our list */
+ while (priv->contents != NULL)
+ ring_call_member_content_remove (
+ RING_CALL_MEMBER_CONTENT (priv->contents->data));
+}
diff --git a/src/ring-call-member.h b/src/ring-call-member.h
new file mode 100644
index 0000000..d80e26b
--- /dev/null
+++ b/src/ring-call-member.h
@@ -0,0 +1,73 @@
+/*
+ * ring-call-member.h - Header for CallMember
+ * Copyright (C) 2010 Collabora Ltd.
+ * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
+ *
+ * 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 __RING_CALL_MEMBER_H__
+#define __RING_CALL_MEMBER_H__
+
+#include <glib-object.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _RingCallMember RingCallMember;
+typedef struct _RingCallMemberPrivate RingCallMemberPrivate;
+typedef struct _RingCallMemberClass RingCallMemberClass;
+
+struct _RingCallMemberClass {
+ GObjectClass parent_class;
+};
+
+struct _RingCallMember {
+ GObject parent;
+ RingCallMemberPrivate *priv;
+};
+
+GType ring_call_member_get_type (void);
+
+/* TYPE MACROS */
+#define RING_TYPE_CALL_MEMBER \
+ (ring_call_member_get_type ())
+#define RING_CALL_MEMBER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), RING_TYPE_CALL_MEMBER, \
+ RingCallMember))
+#define RING_CALL_MEMBER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), RING_TYPE_CALL_MEMBER, \
+ RingCallMemberClass))
+#define RING_IS_CALL_MEMBER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), RING_TYPE_CALL_MEMBER))
+#define RING_IS_CALL_MEMBER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), RING_TYPE_CALL_MEMBER))
+#define RING_CALL_MEMBER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), RING_TYPE_CALL_MEMBER, \
+ RingCallMemberClass))
+
+TpHandle ring_call_member_get_handle(RingCallMember *self);
+
+TpCallMemberFlags ring_call_member_get_flags(RingCallMember *self);
+
+RingConnection * ring_call_member_get_connection(RingCallMember *self);
+
+void ring_call_member_shutdown(RingCallMember *self);
+
+G_END_DECLS
+
+#endif /* #ifndef __RING_CALL_MEMBER_H__*/
diff --git a/src/ring-call-stream.c b/src/ring-call-stream.c
index d79e83f..f8ddd23 100644
--- a/src/ring-call-stream.c
+++ b/src/ring-call-stream.c
@@ -3,6 +3,7 @@
* Copyright ©2010 Collabora Ltd.
* Copyright ©2010 Nokia Corporation
* @author Will Thompson <will.thompson@collabora.co.uk>
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,10 +27,8 @@
static void implement_call_stream (gpointer klass, gpointer unused);
-G_DEFINE_TYPE_WITH_CODE (RingCallStream, ring_call_stream,
- GABBLE_TYPE_BASE_CALL_STREAM,
- G_IMPLEMENT_INTERFACE (RING_TYPE_SVC_CALL_STREAM, implement_call_stream)
-)
+G_DEFINE_TYPE(RingCallStream, ring_call_stream,
+ TP_TYPE_BASE_MEDIA_CALL_STREAM);
static void
ring_call_stream_init (RingCallStream *self)
@@ -53,7 +52,7 @@ ring_call_stream_new (RingConnection *connection,
static void
ring_call_stream_set_sending (
- RingSvcCallStream *self,
+ RingCallStream *self,
gboolean send,
DBusGMethodInvocation *context)
{
@@ -67,7 +66,7 @@ ring_call_stream_set_sending (
static void
ring_call_stream_request_receiving (
- RingSvcCallStream *self,
+ RingCallStream *self,
TpHandle contact,
gboolean receive,
DBusGMethodInvocation *context)
diff --git a/src/ring-call-stream.h b/src/ring-call-stream.h
index d0930d6..67ee728 100644
--- a/src/ring-call-stream.h
+++ b/src/ring-call-stream.h
@@ -3,6 +3,7 @@
* Copyright ©2010 Collabora Ltd.
* Copyright ©2010 Nokia Corporation
* @author Will Thompson <will.thompson@collabora.co.uk>
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,17 +25,24 @@
#include <glib-object.h>
-#include "base-call-stream.h"
+#include <telepathy-glib/telepathy-glib.h>
+
+#include "ring-connection.h"
+
+G_BEGIN_DECLS
typedef struct _RingCallStream RingCallStream;
+typedef struct _RingCallStreamPrivate RingCallStreamPrivate;
typedef struct _RingCallStreamClass RingCallStreamClass;
struct _RingCallStreamClass {
- GabbleBaseCallStreamClass parent_class;
+ TpBaseMediaCallStreamClass parent_class;
};
struct _RingCallStream {
- GabbleBaseCallStream parent;
+ TpBaseMediaCallStream parent;
+
+ RingCallStreamPrivate *priv;
};
GType ring_call_stream_get_type (void);
@@ -58,4 +66,8 @@ RingCallStream *ring_call_stream_new (RingConnection *connection,
(G_TYPE_INSTANCE_GET_CLASS ((obj), RING_TYPE_CALL_STREAM, \
RingCallStreamClass))
+void ring_call_stream_update_member_states(RingCallStream *self);
+
+G_END_DECLS
+
#endif /* RING_CALL_STREAM_H */
diff --git a/src/ring-connection.c b/src/ring-connection.c
index c985795..35c6b3e 100644
--- a/src/ring-connection.c
+++ b/src/ring-connection.c
@@ -4,6 +4,7 @@
* Copyright (C) 2007-2010 Nokia Corporation
* @author Pekka Pessi <first.surname@nokia.com>
* @author Lassi Syrjala <first.surname@nokia.com>
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
*
* This work is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/src/ring-connection.h b/src/ring-connection.h
index 0981860..23b51b1 100644
--- a/src/ring-connection.h
+++ b/src/ring-connection.h
@@ -3,6 +3,7 @@
*
* Copyright (C) 2007-2010 Nokia Corporation
* @author Pekka Pessi <first.surname@nokia.com>
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
*
* This work is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,10 +24,12 @@
#define RING_CONNECTION_H
#include <glib-object.h>
+
#include <telepathy-glib/base-connection.h>
#include <telepathy-glib/base-connection-manager.h>
#include <telepathy-glib/contacts-mixin.h>
-#include <ring-util.h>
+
+#include "ring-util.h"
G_BEGIN_DECLS
diff --git a/src/ring-util.c b/src/ring-util.c
index e332fd3..384afdf 100644
--- a/src/ring-util.c
+++ b/src/ring-util.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2007-2010 Nokia Corporation
* @author Pekka Pessi <first.surname@nokia.com>
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
*
* This work is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/src/ring-util.h b/src/ring-util.h
index df5c65c..a7445b9 100644
--- a/src/ring-util.h
+++ b/src/ring-util.h
@@ -3,7 +3,7 @@
*
* Copyright (C) 2007-2010 Nokia Corporation
* @author Pekka Pessi <first.surname@nokia.com>
- *
+ * @author Tom Swindell <t.swindell@rubyx.co.uk>
* This work is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 0000000..a7f5b61
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,525 @@
+/*
+ * util.c - Source for Ring utility functions
+ * Copyright (C) 2006-2007 Collabora Ltd.
+ * Copyright (C) 2006-2007 Nokia Corporation
+ * @author Robert McQueen <robert.mcqueen@collabora.co.uk>
+ * @author Simon McVittie <simon.mcvittie@collabora.co.uk>
+ *
+ * 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 "config.h"
+#include "util.h"
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gobject/gvaluecollector.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
+
+#define DEBUG_FLAG RING_DEBUG_JID
+
+#include "ring-connection.h"
+
+gchar *
+sha1_hex (const gchar *bytes,
+ guint len)
+{
+ gchar *hex = g_compute_checksum_for_string (G_CHECKSUM_SHA1, bytes, len);
+ guint i;
+
+ for (i = 0; i < SHA1_HASH_SIZE * 2; i++)
+ {
+ g_assert (hex[i] != '\0');
+ hex[i] = g_ascii_tolower (hex[i]);
+ }
+
+ g_assert (hex[SHA1_HASH_SIZE * 2] == '\0');
+
+ return hex;
+}
+
+void
+sha1_bin (const gchar *bytes,
+ guint len,
+ guchar out[SHA1_HASH_SIZE])
+{
+ GChecksum *checksum = g_checksum_new (G_CHECKSUM_SHA1);
+ gsize out_len = SHA1_HASH_SIZE;
+
+ g_assert (g_checksum_type_get_length (G_CHECKSUM_SHA1) == SHA1_HASH_SIZE);
+ g_checksum_update (checksum, (const guchar *) bytes, len);
+ g_checksum_get_digest (checksum, out, &out_len);
+ g_assert (out_len == SHA1_HASH_SIZE);
+ g_checksum_free (checksum);
+}
+
+
+/** ring_generate_id:
+ *
+ * RFC4122 version 4 compliant random UUIDs generator.
+ *
+ * Returns: A string with RFC41122 version 4 random UUID, must be freed with
+ * g_free().
+ */
+gchar *
+ring_generate_id (void)
+{
+ GRand *grand;
+ gchar *str;
+ struct {
+ guint32 time_low;
+ guint16 time_mid;
+ guint16 time_hi_and_version;
+ guint8 clock_seq_hi_and_rsv;
+ guint8 clock_seq_low;
+ guint16 node_hi;
+ guint32 node_low;
+ } uuid;
+
+ /* Fill with random. Every new GRand are seede with 128 bit read from
+ * /dev/urandom (or the current time on non-unix systems). This makes the
+ * random source good enough for our usage, but may not be suitable for all
+ * situation outside Ring. */
+ grand = g_rand_new ();
+ uuid.time_low = g_rand_int (grand);
+ uuid.time_mid = (guint16) g_rand_int_range (grand, 0, G_MAXUINT16);
+ uuid.time_hi_and_version = (guint16) g_rand_int_range (grand, 0, G_MAXUINT16);
+ uuid.clock_seq_hi_and_rsv = (guint8) g_rand_int_range (grand, 0, G_MAXUINT8);
+ uuid.clock_seq_low = (guint8) g_rand_int_range (grand, 0, G_MAXUINT8);
+ uuid.node_hi = (guint16) g_rand_int_range (grand, 0, G_MAXUINT16);
+ uuid.node_low = g_rand_int (grand);
+ g_rand_free (grand);
+
+ /* Set the two most significant bits (bits 6 and 7) of the
+ * clock_seq_hi_and_rsv to zero and one, respectively. */
+ uuid.clock_seq_hi_and_rsv = (uuid.clock_seq_hi_and_rsv & 0x3F) | 0x80;
+
+ /* Set the four most significant bits (bits 12 through 15) of the
+ * time_hi_and_version field to 4 */
+ uuid.time_hi_and_version = (uuid.time_hi_and_version & 0x0fff) | 0x4000;
+
+ str = g_strdup_printf ("%08x-%04x-%04x-%02x%02x-%04x%08x",
+ uuid.time_low,
+ uuid.time_mid,
+ uuid.time_hi_and_version,
+ uuid.clock_seq_hi_and_rsv,
+ uuid.clock_seq_low,
+ uuid.node_hi,
+ uuid.node_low);
+
+ return str;
+}
+
+/**
+ * ring_get_room_handle_from_jid:
+ * @room_repo: The %TP_HANDLE_TYPE_ROOM handle repository
+ * @jid: A JID
+ *
+ * Given a JID seen in the from="" attribute on a stanza, work out whether
+ * it's something to do with a MUC, and if so, return its handle.
+ *
+ * Returns: The handle of the MUC, if the JID refers to either a MUC
+ * we're in, or a contact's channel-specific JID inside a MUC.
+ * Returns 0 if the JID is either invalid, or nothing to do with a
+ * known MUC (typically this will mean it's the global JID of a contact).
+ */
+TpHandle
+ring_get_room_handle_from_jid (TpHandleRepoIface *room_repo,
+ const gchar *jid)
+{
+ TpHandle handle;
+ gchar *room;
+
+ room = ring_remove_resource (jid);
+ if (room == NULL)
+ return 0;
+
+ handle = tp_handle_lookup (room_repo, room, NULL, NULL);
+ g_free (room);
+ return handle;
+}
+
+#define INVALID_HANDLE(e, f, ...) \
+ G_STMT_START { \
+ DEBUG (f, ##__VA_ARGS__); \
+ g_set_error (e, TP_ERROR, TP_ERROR_INVALID_HANDLE, f, ##__VA_ARGS__);\
+ } G_STMT_END
+
+gchar *
+ring_remove_resource (const gchar *jid)
+{
+ char *slash = strchr (jid, '/');
+ gchar *buf;
+
+ if (slash == NULL)
+ return g_strdup (jid);
+
+ /* The user and domain parts can't contain '/', assuming it's valid */
+ buf = g_malloc (slash - jid + 1);
+ strncpy (buf, jid, slash - jid);
+ buf[slash - jid] = '\0';
+
+ return buf;
+}
+
+gchar *
+ring_encode_jid (
+ const gchar *node,
+ const gchar *domain,
+ const gchar *resource)
+{
+ gchar *tmp, *ret;
+
+ g_return_val_if_fail (domain != NULL, NULL);
+
+ if (node != NULL && resource != NULL)
+ tmp = g_strdup_printf ("%s@%s/%s", node, domain, resource);
+ else if (node != NULL)
+ tmp = g_strdup_printf ("%s@%s", node, domain);
+ else if (resource != NULL)
+ tmp = g_strdup_printf ("%s/%s", domain, resource);
+ else
+ tmp = g_strdup (domain);
+
+ ret = g_utf8_normalize (tmp, -1, G_NORMALIZE_NFKC);
+ g_free (tmp);
+ return ret;
+}
+
+typedef struct {
+ GObject *instance;
+ GObject *user_data;
+ gulong handler_id;
+} WeakHandlerCtx;
+
+static WeakHandlerCtx *
+whc_new (GObject *instance,
+ GObject *user_data)
+{
+ WeakHandlerCtx *ctx = g_slice_new0 (WeakHandlerCtx);
+
+ ctx->instance = instance;
+ ctx->user_data = user_data;
+
+ return ctx;
+}
+
+static void
+whc_free (WeakHandlerCtx *ctx)
+{
+ g_slice_free (WeakHandlerCtx, ctx);
+}
+
+static void user_data_destroyed_cb (gpointer, GObject *);
+
+static void
+instance_destroyed_cb (gpointer ctx_,
+ GObject *where_the_instance_was)
+{
+ WeakHandlerCtx *ctx = ctx_;
+
+ /* No need to disconnect the signal here, the instance has gone away. */
+ g_object_weak_unref (ctx->user_data, user_data_destroyed_cb, ctx);
+ whc_free (ctx);
+}
+
+static void
+user_data_destroyed_cb (gpointer ctx_,
+ GObject *where_the_user_data_was)
+{
+ WeakHandlerCtx *ctx = ctx_;
+
+ g_signal_handler_disconnect (ctx->instance, ctx->handler_id);
+ g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx);
+ whc_free (ctx);
+}
+
+/**
+ * ring_signal_connect_weak:
+ * @instance: the instance to connect to.
+ * @detailed_signal: a string of the form "signal-name::detail".
+ * @c_handler: the GCallback to connect.
+ * @user_data: an object to pass as data to c_handler calls.
+ *
+ * Connects a #GCallback function to a signal for a particular object, as if
+ * with g_signal_connect(). Additionally, arranges for the signal handler to be
+ * disconnected if @user_data is destroyed.
+ *
+ * This is intended to be a convenient way for objects to use themselves as
+ * user_data for callbacks without having to explicitly disconnect all the
+ * handlers in their finalizers.
+ */
+void
+ring_signal_connect_weak (gpointer instance,
+ const gchar *detailed_signal,
+ GCallback c_handler,
+ GObject *user_data)
+{
+ GObject *instance_obj = G_OBJECT (instance);
+ WeakHandlerCtx *ctx = whc_new (instance_obj, user_data);
+
+ ctx->handler_id = g_signal_connect (instance, detailed_signal, c_handler,
+ user_data);
+
+ g_object_weak_ref (instance_obj, instance_destroyed_cb, ctx);
+ g_object_weak_ref (user_data, user_data_destroyed_cb, ctx);
+}
+
+typedef struct {
+ GSourceFunc function;
+ GObject *object;
+ guint source_id;
+} WeakIdleCtx;
+
+static void
+idle_weak_ref_notify (gpointer data,
+ GObject *dead_object)
+{
+ g_source_remove (GPOINTER_TO_UINT (data));
+}
+
+static void
+idle_removed (gpointer data)
+{
+ WeakIdleCtx *ctx = (WeakIdleCtx *) data;
+
+ g_slice_free (WeakIdleCtx, ctx);
+}
+
+static gboolean
+idle_callback (gpointer data)
+{
+ WeakIdleCtx *ctx = (WeakIdleCtx *) data;
+
+ if (ctx->function ((gpointer) ctx->object))
+ {
+ return TRUE;
+ }
+ else
+ {
+ g_object_weak_unref (
+ ctx->object, idle_weak_ref_notify, GUINT_TO_POINTER (ctx->source_id));
+ return FALSE;
+ }
+}
+
+/* Like g_idle_add(), but cancel the callback if the provided object is
+ * finalized.
+ */
+guint
+ring_idle_add_weak (GSourceFunc function,
+ GObject *object)
+{
+ WeakIdleCtx *ctx;
+
+ ctx = g_slice_new0 (WeakIdleCtx);
+ ctx->function = function;
+ ctx->object = object;
+ ctx->source_id = g_idle_add_full (
+ G_PRIORITY_DEFAULT_IDLE, idle_callback, ctx, idle_removed);
+
+ g_object_weak_ref (
+ object, idle_weak_ref_notify, GUINT_TO_POINTER (ctx->source_id));
+ return ctx->source_id;
+}
+
+GPtrArray *
+ring_g_ptr_array_copy (GPtrArray *source)
+{
+ GPtrArray *ret = g_ptr_array_sized_new (source->len);
+ guint i;
+
+ for (i = 0; i < source->len; i++)
+ g_ptr_array_add (ret, g_ptr_array_index (source, i));
+
+ return ret;
+}
+
+gchar *
+ring_peer_to_jid (RingConnection *conn,
+ TpHandle peer,
+ const gchar *resource)
+{
+ TpHandleRepoIface *repo = tp_base_connection_get_handles (
+ TP_BASE_CONNECTION (conn), TP_HANDLE_TYPE_CONTACT);
+ const gchar *target = tp_handle_inspect (repo, peer);
+
+ if (resource == NULL)
+ return g_strdup (target);
+
+ return g_strdup_printf ("%s/%s", target, resource);
+}
+
+/* Like wocky_enum_from_nick, but for GFlagsValues instead. */
+gboolean
+ring_flag_from_nick (GType flag_type,
+ const gchar *nick,
+ guint *value)
+{
+ GFlagsClass *klass = g_type_class_ref (flag_type);
+ GFlagsValue *flag_value;
+
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ flag_value = g_flags_get_value_by_nick (klass, nick);
+ g_type_class_unref (klass);
+
+ if (flag_value != NULL)
+ {
+ *value = flag_value->value;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+/**
+ * ring_simple_async_succeed_or_fail_in_idle:
+ * @self: the source object for an asynchronous function
+ * @callback: a callback to call when @todo things have been done
+ * @user_data: user data for the callback
+ * @source_tag: the source tag for a #GSimpleAsyncResult
+ * @error: (allow-none): %NULL to indicate success, or an error on failure
+ *
+ * Create a new #GSimpleAsyncResult and schedule it to call its callback
+ * in an idle. If @error is %NULL, report success with
+ * tp_simple_async_report_success_in_idle(); if @error is non-%NULL,
+ * use g_simple_async_report_gerror_in_idle().
+ */
+void
+ring_simple_async_succeed_or_fail_in_idle (gpointer self,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ gpointer source_tag,
+ const GError *error)
+{
+ if (error == NULL)
+ {
+ tp_simple_async_report_success_in_idle (self, callback, user_data,
+ source_tag);
+ }
+ else
+ {
+ /* not const-correct yet: GNOME #622004 */
+ g_simple_async_report_gerror_in_idle (self, callback, user_data,
+ (GError *) error);
+ }
+}
+
+/**
+ * ring_simple_async_countdown_new:
+ * @self: the source object for an asynchronous function
+ * @callback: a callback to call when @todo things have been done
+ * @user_data: user data for the callback
+ * @source_tag: the source tag for a #GSimpleAsyncResult
+ * @todo: number of things to do before calling @callback (at least 1)
+ *
+ * Create a new #GSimpleAsyncResult that will call its callback when a number
+ * of asynchronous operations have happened.
+ *
+ * An internal counter is initialized to @todo, incremented with
+ * ring_simple_async_countdown_inc() or decremented with
+ * ring_simple_async_countdown_dec().
+ *
+ * When that counter reaches zero, if an error has been set with
+ * g_simple_async_result_set_from_error() or similar, the operation fails;
+ * otherwise, it succeeds.
+ *
+ * The caller must not use the operation result functions, such as
+ * g_simple_async_result_get_op_res_gssize() - this async result is only
+ * suitable for "void" async methods which return either success or a #GError,
+ * i.e. the same signature as g_async_initable_init_async().
+ *
+ * Returns: (transfer full): a counter
+ */
+GSimpleAsyncResult *
+ring_simple_async_countdown_new (gpointer self,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ gpointer source_tag,
+ gssize todo)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (todo >= 1, NULL);
+
+ simple = g_simple_async_result_new (self, callback, user_data, source_tag);
+ /* We (ab)use the op_res member as a count of things to do. When
+ * it reaches zero, the operation completes with any error that has been
+ * set, or with success. */
+ g_simple_async_result_set_op_res_gssize (simple, todo);
+
+ /* we keep one extra reference as long as the counter is nonzero */
+ g_object_ref (simple);
+
+ return simple;
+}
+
+/**
+ * ring_simple_async_countdown_inc:
+ * @simple: a result created by ring_simple_async_countdown_new()
+ *
+ * Increment the counter in @simple, indicating that an additional async
+ * operation has been started. An additional call to
+ * ring_simple_async_countdown_dec() will be needed to make @simple
+ * call its callback.
+ */
+void
+ring_simple_async_countdown_inc (GSimpleAsyncResult *simple)
+{
+ gssize todo = g_simple_async_result_get_op_res_gssize (simple);
+
+ g_return_if_fail (todo >= 1);
+ g_simple_async_result_set_op_res_gssize (simple, todo + 1);
+}
+
+/**
+ * ring_simple_async_countdown_dec:
+ * @simple: a result created by ring_simple_async_countdown_new()
+ *
+ * Decrement the counter in @simple. If the number of things to do has
+ * reached zero, schedule @simple to call its callback in an idle, then
+ * unref it.
+ *
+ * When one of the asynchronous operations needed for @simple succeeds,
+ * this should be signalled by a call to this function.
+ *
+ * When one of the asynchronous operations needed for @simple fails,
+ * this should be signalled by a call to g_simple_async_result_set_from_error()
+ * (or one of the similar functions), followed by a call to this function.
+ * If more than one async operation fails in this way, the #GError from the
+ * last failure will be used.
+ */
+void
+ring_simple_async_countdown_dec (GSimpleAsyncResult *simple)
+{
+ gssize todo = g_simple_async_result_get_op_res_gssize (simple);
+
+ g_simple_async_result_set_op_res_gssize (simple, --todo);
+
+ if (todo <= 0)
+ {
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ }
+}
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..a3fa43c
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,110 @@
+/*
+ * util.h - Headers for Ring utility functions
+ * Copyright (C) 2006 Collabora Ltd.
+ * Copyright (C) 2006 Nokia Corporation
+ * @author Robert McQueen <robert.mcqueen@collabora.co.uk>
+ *
+ * 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_UTIL_H__
+#define __GABBLE_UTIL_H__
+
+#include <config.h>
+
+#include <glib.h>
+#include <telepathy-glib/telepathy-glib.h>
+
+#include "ring-connection.h"
+
+/* Guarantees that the resulting hash is in lower-case */
+gchar *sha1_hex (const gchar *bytes, guint len);
+
+/* A SHA1 digest is 20 bytes long */
+#define SHA1_HASH_SIZE 20
+void sha1_bin (const gchar *bytes, guint len, guchar out[SHA1_HASH_SIZE]);
+
+gchar *ring_generate_id (void);
+
+G_GNUC_WARN_UNUSED_RESULT
+gchar *ring_encode_jid (const gchar *node, const gchar *domain,
+ const gchar *resource);
+
+gchar *ring_remove_resource (const gchar *jid);
+gchar *ring_normalize_room (TpHandleRepoIface *repo, const gchar *jid,
+ gpointer context, GError **error);
+TpHandle ring_get_room_handle_from_jid (TpHandleRepoIface *room_repo,
+ const gchar *jid);
+
+void ring_signal_connect_weak (gpointer instance, const gchar *detailed_signal,
+ GCallback c_handler, GObject *user_data);
+guint ring_idle_add_weak (GSourceFunc function, GObject *object);
+
+GPtrArray *ring_g_ptr_array_copy (GPtrArray *source);
+
+gchar * ring_peer_to_jid (RingConnection *conn,
+ TpHandle peer,
+ const gchar *resource);
+
+gboolean
+ring_flag_from_nick (GType flag_type, const gchar *nick,
+ guint *value);
+
+void ring_simple_async_succeed_or_fail_in_idle (gpointer self,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ gpointer source_tag,
+ const GError *error);
+
+GSimpleAsyncResult *ring_simple_async_countdown_new (gpointer self,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ gpointer source_tag,
+ gssize todo);
+void ring_simple_async_countdown_inc (GSimpleAsyncResult *simple);
+void ring_simple_async_countdown_dec (GSimpleAsyncResult *simple);
+
+/* Boilerplate for telling servers which implement XEP-0079 not to store these
+ * messages for delivery later. Include it in your call to wocky_stanza_build()
+ * like so:
+ *
+ * wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE,
+ * NULL, jid,
+ * '(', "close",
+ * ':', NS_TUBES,
+ * '@', "tube", id_str,
+ * ')',
+ * RING_AMP_DO_NOT_STORE_SPEC,
+ * NULL);
+ *
+ * Every 1000th user will win a Marshall amplifier!
+ */
+#define RING_AMP_DO_NOT_STORE_SPEC \
+ '(', "amp", \
+ ':', NS_AMP, \
+ '(', "rule", \
+ '@', "condition", "deliver-at", \
+ '@', "value", "stored", \
+ '@', "action", "error", \
+ ')', \
+ '(', "rule", \
+ '@', "condition", "match-resource", \
+ '@', "value", "exact", \
+ '@', "action", "error", \
+ ')', \
+ ')'
+
+
+#endif /* __GABBLE_UTIL_H__ */