diff options
author | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2010-01-12 15:00:36 +0000 |
---|---|---|
committer | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2010-02-18 18:22:39 +0000 |
commit | 916d3d729a5b71c36c7c0f831b846ef4fd249ddf (patch) | |
tree | f24598d03253c749e9c06cbb9a303174ea81c835 /src/call-channel.c | |
parent | e995c1cb20fac30aa378365394aa986498658abb (diff) |
Split a BaseCallChannel out of CallChannel
Both Muji related call channels and 1-to-1 call channel should be able to share
quite some code. The main difference is in setting up the call. This is a very
minimal split, more 1-to-1 call specific code will move out of the base class
into the call-channel
Diffstat (limited to 'src/call-channel.c')
-rw-r--r-- | src/call-channel.c | 965 |
1 files changed, 20 insertions, 945 deletions
diff --git a/src/call-channel.c b/src/call-channel.c index 9c43877e4..a79e355bb 100644 --- a/src/call-channel.c +++ b/src/call-channel.c @@ -29,8 +29,6 @@ #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> @@ -47,66 +45,16 @@ #include "debug.h" -static void channel_iface_init (gpointer, gpointer); -static void call_iface_init (gpointer, gpointer); static void async_initable_iface_init (GAsyncInitableIface *iface); -static void call_channel_setup (GabbleCallChannel *self); -static const char *call_channel_add_content (GabbleCallChannel *self, - GabbleJingleContent *c, GabbleCallContentDisposition disposition); - -static void call_session_state_changed_cb (GabbleJingleSession *session, - GParamSpec *param, GabbleCallChannel *self); -static void call_session_new_content_cb (GabbleJingleSession *session, - GabbleJingleContent *c, GabbleCallChannel *self); - G_DEFINE_TYPE_WITH_CODE(GabbleCallChannel, gabble_call_channel, - G_TYPE_OBJECT, + GABBLE_TYPE_BASE_CALL_CHANNEL, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init); - G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_CHANNEL_TYPE_CALL, - call_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, - tp_dbus_properties_mixin_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL); - G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL) ); -static const gchar *gabble_call_channel_interfaces[] = { - NULL -}; - /* properties */ enum { - PROP_OBJECT_PATH = 1, - PROP_CHANNEL_TYPE, - PROP_HANDLE_TYPE, - PROP_TARGET_HANDLE, - PROP_TARGET_ID, - - PROP_REQUESTED, - PROP_CONNECTION, - PROP_CREATOR, - PROP_CREATOR_ID, - - PROP_INTERFACES, - PROP_CHANNEL_DESTROYED, - PROP_CHANNEL_PROPERTIES, - 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, - - PROP_SESSION, LAST_PROPERTY }; @@ -114,105 +62,12 @@ enum /* private structure */ struct _GabbleCallChannelPrivate { - GabbleConnection *conn; - gchar *object_path; - GabbleJingleSession *session; - - TpHandle creator; - TpHandle target; - - gboolean closed; - - gboolean initial_audio; - gboolean initial_video; - gboolean registered; - gboolean requested; - gboolean dispose_has_run; - - GList *contents; - - gchar *transport_ns; - - GabbleCallState state; - guint flags; - GHashTable *details; - GValueArray *reason; - - GHashTable *members; }; static void gabble_call_channel_constructed (GObject *obj) { - GabbleCallChannel *self = GABBLE_CALL_CHANNEL (obj); - GabbleCallChannelPrivate *priv = self->priv; - TpBaseConnection *conn; - TpHandleRepoIface *contact_handles; - - conn = (TpBaseConnection *) priv->conn; - contact_handles = tp_base_connection_get_handles (conn, - TP_HANDLE_TYPE_CONTACT); - - priv->requested = (priv->session == NULL); - - if (priv->session != NULL) - priv->creator = priv->session->peer; - else - priv->creator = conn->self_handle; - - g_hash_table_insert (priv->members, - GUINT_TO_POINTER (priv->target), - GUINT_TO_POINTER (0)); - - /* automatically add creator to channel, but also ref them again (because - * priv->creator is the InitiatorHandle) */ - g_assert (priv->creator != 0); - tp_handle_ref (contact_handles, priv->creator); - - if (priv->session != NULL) - { - GList *contents, *l; - contents = gabble_jingle_session_get_contents (priv->session); - - gabble_signal_connect_weak (priv->session, "notify::state", - G_CALLBACK (call_session_state_changed_cb), obj); - gabble_signal_connect_weak (priv->session, "new-content", - G_CALLBACK (call_session_new_content_cb), obj); - - for (l = contents; l != NULL; l = g_list_next (l)) - { - GabbleJingleContent *content = GABBLE_JINGLE_CONTENT (l->data); - JingleMediaType mtype; - - if (priv->transport_ns == NULL) - g_object_get (content, "transport-ns", - &priv->transport_ns, - NULL); - - call_channel_add_content (self, content, - GABBLE_CALL_CONTENT_DISPOSITION_INITIAL); - - g_object_get (content, "media-type", &mtype, NULL); - switch (mtype) - { - case JINGLE_MEDIA_TYPE_AUDIO: - priv->initial_audio = TRUE; - break; - case JINGLE_MEDIA_TYPE_VIDEO: - priv->initial_video = TRUE; - break; - default: - break; - } - } - } - - if (priv->requested) - priv->state = GABBLE_CALL_STATE_PENDING_INITIATOR; - else - priv->state = GABBLE_CALL_STATE_PENDING_RECEIVER; - if (G_OBJECT_CLASS (gabble_call_channel_parent_class)->constructed != NULL) G_OBJECT_CLASS (gabble_call_channel_parent_class)->constructed (obj); } @@ -224,16 +79,6 @@ gabble_call_channel_init (GabbleCallChannel *self) GABBLE_TYPE_CALL_CHANNEL, GabbleCallChannelPrivate); self->priv = priv; - - priv->reason = gabble_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 (g_direct_hash, g_direct_equal); } static void gabble_call_channel_dispose (GObject *object); @@ -245,119 +90,8 @@ gabble_call_channel_get_property (GObject *object, GValue *value, GParamSpec *pspec) { - GabbleCallChannel *chan = GABBLE_CALL_CHANNEL (object); - GabbleCallChannelPrivate *priv = chan->priv; - TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn; - switch (property_id) { - case PROP_OBJECT_PATH: - g_value_set_string (value, priv->object_path); - break; - case PROP_CHANNEL_TYPE: - g_value_set_static_string (value, GABBLE_IFACE_CHANNEL_TYPE_CALL); - break; - case PROP_HANDLE_TYPE: - g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); - break; - case PROP_TARGET_HANDLE: - g_value_set_uint (value, priv->target); - break; - case PROP_TARGET_ID: - { - TpHandleRepoIface *repo = tp_base_connection_get_handles ( - base_conn, TP_HANDLE_TYPE_CONTACT); - const gchar *target_id = tp_handle_inspect (repo, priv->target); - - g_value_set_string (value, target_id); - } - break; - case PROP_CONNECTION: - g_value_set_object (value, priv->conn); - break; - case PROP_CREATOR: - g_value_set_uint (value, priv->creator); - break; - case PROP_CREATOR_ID: - { - TpHandleRepoIface *repo = tp_base_connection_get_handles ( - base_conn, TP_HANDLE_TYPE_CONTACT); - - g_value_set_string (value, tp_handle_inspect (repo, priv->creator)); - } - break; - case PROP_REQUESTED: - g_value_set_boolean (value, priv->requested); - break; - case PROP_INTERFACES: - g_value_set_boxed (value, gabble_call_channel_interfaces); - break; - case PROP_CHANNEL_DESTROYED: - g_value_set_boolean (value, priv->closed); - break; - case PROP_CHANNEL_PROPERTIES: - g_value_take_boxed (value, - tp_dbus_properties_mixin_make_properties_hash (object, - TP_IFACE_CHANNEL, "TargetHandle", - TP_IFACE_CHANNEL, "TargetHandleType", - TP_IFACE_CHANNEL, "ChannelType", - TP_IFACE_CHANNEL, "TargetID", - TP_IFACE_CHANNEL, "InitiatorHandle", - TP_IFACE_CHANNEL, "InitiatorID", - TP_IFACE_CHANNEL, "Requested", - TP_IFACE_CHANNEL, "Interfaces", - GABBLE_IFACE_CHANNEL_TYPE_CALL, "InitialAudio", - GABBLE_IFACE_CHANNEL_TYPE_CALL, "InitialVideo", - GABBLE_IFACE_CHANNEL_TYPE_CALL, "MutableContents", - NULL)); - break; - case PROP_SESSION: - g_value_set_object (value, priv->session); - break; - case PROP_INITIAL_AUDIO: - g_value_set_boolean (value, priv->initial_audio); - break; - case PROP_INITIAL_VIDEO: - g_value_set_boolean (value, priv->initial_video); - break; - case PROP_MUTABLE_CONTENTS: - g_value_set_boolean (value, - gabble_jingle_session_can_modify_contents (priv->session)); - 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)) - { - GabbleCallContent *c = GABBLE_CALL_CONTENT (l->data); - g_ptr_array_add (arr, - (gpointer) gabble_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, FALSE); - 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; @@ -370,90 +104,19 @@ gabble_call_channel_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - GabbleCallChannel *chan = GABBLE_CALL_CHANNEL (object); - GabbleCallChannelPrivate *priv = chan->priv; - switch (property_id) { - case PROP_OBJECT_PATH: - g_free (priv->object_path); - priv->object_path = g_value_dup_string (value); - break; - case PROP_HANDLE_TYPE: - case PROP_CHANNEL_TYPE: - /* these properties are writable in the interface, but not actually - * meaningfully changable on this channel, so we do nothing */ - break; - case PROP_TARGET_HANDLE: - priv->target = g_value_get_uint (value); - break; - case PROP_CONNECTION: - priv->conn = g_value_get_object (value); - break; - case PROP_CREATOR: - priv->creator = g_value_get_uint (value); - break; - case PROP_SESSION: - g_assert (priv->session == NULL); - priv->session = g_value_dup_object (value); - break; - case PROP_INITIAL_AUDIO: - priv->initial_audio = g_value_get_boolean (value); - break; - case PROP_INITIAL_VIDEO: - priv->initial_video = g_value_get_boolean (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } - static void gabble_call_channel_class_init ( GabbleCallChannelClass *gabble_call_channel_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_call_channel_class); - GParamSpec *param_spec; - static TpDBusPropertiesMixinPropImpl channel_props[] = { - { "TargetHandleType", "handle-type", NULL }, - { "TargetHandle", "handle", NULL }, - { "TargetID", "target-id", NULL }, - { "ChannelType", "channel-type", NULL }, - { "Interfaces", "interfaces", NULL }, - { "Requested", "requested", NULL }, - { "InitiatorHandle", "creator", NULL }, - { "InitiatorID", "creator-id", NULL }, - { NULL } - }; - 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 } - }; - - static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { - { TP_IFACE_CHANNEL, - tp_dbus_properties_mixin_getter_gobject_properties, - NULL, - channel_props, - }, - { GABBLE_IFACE_CHANNEL_TYPE_CALL, - tp_dbus_properties_mixin_getter_gobject_properties, - NULL, - call_props, - }, - { NULL } - }; g_type_class_add_private (gabble_call_channel_class, sizeof (GabbleCallChannelPrivate)); @@ -465,137 +128,6 @@ gabble_call_channel_class_init ( object_class->dispose = gabble_call_channel_dispose; object_class->finalize = gabble_call_channel_finalize; - - g_object_class_override_property (object_class, PROP_OBJECT_PATH, - "object-path"); - g_object_class_override_property (object_class, PROP_CHANNEL_TYPE, - "channel-type"); - g_object_class_override_property (object_class, PROP_HANDLE_TYPE, - "handle-type"); - g_object_class_override_property (object_class, PROP_TARGET_HANDLE, - "handle"); - - g_object_class_override_property (object_class, PROP_CHANNEL_DESTROYED, - "channel-destroyed"); - g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES, - "channel-properties"); - - param_spec = g_param_spec_string ("target-id", "Target JID", - "Target JID of the call" , - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec); - - param_spec = g_param_spec_object ("connection", "GabbleConnection object", - "Gabble connection object that owns this media channel object.", - GABBLE_TYPE_CONNECTION, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); - - param_spec = g_param_spec_uint ("creator", "Channel creator", - "The TpHandle representing the contact who created the channel.", - 0, G_MAXUINT32, 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_string ("creator-id", "Creator bare JID", - "The bare JID obtained by inspecting the creator handle.", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_CREATOR_ID, param_spec); - - param_spec = g_param_spec_boolean ("requested", "Requested?", - "True if this channel was requested by the local user", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_REQUESTED, param_spec); - - param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces", - "Additional Channel.Interface.* interfaces", - 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_object ("session", "GabbleJingleSession object", - "Jingle session associated with this media channel object.", - GABBLE_TYPE_JINGLE_SESSION, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_SESSION, param_spec); - - param_spec = g_param_spec_boolean ("initial-audio", "InitialAudio", - "Whether the channel initially contained an audio stream", - FALSE, - G_PARAM_CONSTRUCT_ONLY | 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_ONLY | 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", - GABBLE_CALL_STATE_UNKNOWN, - NUM_GABBLE_CALL_STATES, - GABBLE_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", - GABBLE_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", - GABBLE_HASH_TYPE_CALL_MEMBER_MAP, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_CALL_MEMBERS, - param_spec); - - gabble_call_channel_class->dbus_props_class.interfaces = prop_interfaces; - tp_dbus_properties_mixin_class_init (object_class, - G_STRUCT_OFFSET (GabbleCallChannelClass, dbus_props_class)); } void @@ -603,21 +135,12 @@ gabble_call_channel_dispose (GObject *object) { GabbleCallChannel *self = GABBLE_CALL_CHANNEL (object); GabbleCallChannelPrivate *priv = self->priv; - GList *l; if (priv->dispose_has_run) return; self->priv->dispose_has_run = TRUE; - for (l = priv->contents; l != NULL; l = g_list_next (l)) - { - gabble_call_content_deinit (l->data); - } - - g_list_free (priv->contents); - priv->contents = NULL; - if (G_OBJECT_CLASS (gabble_call_channel_parent_class)->dispose) G_OBJECT_CLASS (gabble_call_channel_parent_class)->dispose (object); } @@ -625,456 +148,10 @@ gabble_call_channel_dispose (GObject *object) void gabble_call_channel_finalize (GObject *object) { - GabbleCallChannel *self = GABBLE_CALL_CHANNEL (object); - GabbleCallChannelPrivate *priv = self->priv; - - g_hash_table_unref (priv->details); - g_value_array_free (priv->reason); - g_free (self->priv->object_path); - g_free (self->priv->transport_ns); - - g_hash_table_unref (self->priv->members); - G_OBJECT_CLASS (gabble_call_channel_parent_class)->finalize (object); } static void -emit_call_state_changed (GabbleCallChannel *self) -{ - GabbleCallChannelPrivate *priv = self->priv; - - if (priv->state != GABBLE_CALL_STATE_PENDING_RECEIVER) - priv->flags &= ~GABBLE_CALL_FLAG_LOCALLY_RINGING; - - gabble_svc_channel_type_call_emit_call_state_changed (self, priv->state, - priv->flags, priv->reason, priv->details); -} - -static void -call_session_state_changed_cb (GabbleJingleSession *session, - GParamSpec *param, - GabbleCallChannel *self) -{ - GabbleCallChannelPrivate *priv = self->priv; - JingleSessionState state; - - g_object_get (session, "state", &state, NULL); - - if (state == JS_STATE_ACTIVE && priv->state != GABBLE_CALL_STATE_ACCEPTED) - { - priv->state = GABBLE_CALL_STATE_ACCEPTED; - emit_call_state_changed (self); - - return; - } - - if (state == JS_STATE_ENDED && priv->state < GABBLE_CALL_STATE_ENDED) - { - priv->state = GABBLE_CALL_STATE_ENDED; - emit_call_state_changed (self); - return; - } -} - -static void -call_session_new_content_cb (GabbleJingleSession *session, - GabbleJingleContent *c, - GabbleCallChannel *self) -{ - const gchar *path; - JingleMediaType type; - - /* This will need another condition when early media is supported */ - if (gabble_jingle_content_is_created_by_us (c)) - return; - - /* Not safe if the session would contain non-JingleMediaRtp content */ - g_object_get (c, "media-type", &type, NULL); - - path = call_channel_add_content (self, c, - GABBLE_CALL_CONTENT_DISPOSITION_NONE); - gabble_svc_channel_type_call_emit_content_added (self, path, type); -} - -static const gchar * -call_channel_add_content (GabbleCallChannel *self, - GabbleJingleContent *c, - GabbleCallContentDisposition disposition) -{ - GabbleCallChannelPrivate *priv = self->priv; - gchar *object_path; - GabbleCallContent *content; - TpHandle creator; - - object_path = g_strdup_printf ("%s/Content%p", priv->object_path, c); - - if (gabble_jingle_content_is_created_by_us (c)) - creator = ((TpBaseConnection *) priv->conn)->self_handle; - else - creator = priv->session->peer; - - content = g_object_new (GABBLE_TYPE_CALL_CONTENT, - "connection", priv->conn, - "object-path", object_path, - "jingle-content", c, - "target-handle", priv->target, - "disposition", disposition, - "creator", creator, - NULL); - - g_free (object_path); - - priv->contents = g_list_prepend (priv->contents, content); - - return gabble_call_content_get_object_path (content); -} - -static const gchar * -call_channel_create_content (GabbleCallChannel *self, - const gchar *name, - JingleMediaType type, - GabbleCallContentDisposition disposition, - GError **error) -{ - GabbleCallChannelPrivate *priv = self->priv; - const gchar *content_ns; - GabbleJingleContent *c; - const gchar *peer_resource; - - peer_resource = gabble_jingle_session_get_peer_resource (priv->session); - - 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 (priv->conn, priv->target, - peer_resource, type); - - if (content_ns == NULL) - { - g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE, - "Content type %d not available for this resource", type); - return NULL; - } - - DEBUG ("Creating new jingle content with ns %s : %s", - content_ns, priv->transport_ns); - - c = gabble_jingle_session_add_content (priv->session, - type, name, content_ns, priv->transport_ns); - - g_assert (c != NULL); - - return call_channel_add_content (self, c, disposition); -} - - -static void -call_channel_setup (GabbleCallChannel *self) -{ - GabbleCallChannelPrivate *priv = self->priv; - DBusGConnection *bus; - - /* register object on the bus */ - bus = tp_get_bus (); - DEBUG ("Registering %s", priv->object_path); - dbus_g_connection_register_g_object (bus, priv->object_path, - G_OBJECT (self)); - - priv->registered = TRUE; -} - -void -gabble_call_channel_close (GabbleCallChannel *self) -{ - GabbleCallChannelPrivate *priv = self->priv; - DEBUG ("Closing media channel %s", self->priv->object_path); - - if (!priv->closed) - { - priv->closed = TRUE; - if (priv->session != NULL) - gabble_jingle_session_terminate (priv->session, - TP_CHANNEL_GROUP_CHANGE_REASON_NONE, NULL, NULL); - - tp_svc_channel_emit_closed (self); - } -} - -/** - * gabble_call_channel_close_async: - * - * Implements D-Bus method Close - * on interface org.freedesktop.Telepathy.Channel - */ -static void -gabble_call_channel_close_async (TpSvcChannel *iface, - DBusGMethodInvocation *context) -{ - GabbleCallChannel *self = GABBLE_CALL_CHANNEL (iface); - - DEBUG ("called"); - gabble_call_channel_close (self); - tp_svc_channel_return_from_close (context); -} - -/** - * gabble_call_channel_get_channel_type - * - * Implements D-Bus method GetChannelType - * on interface org.freedesktop.Telepathy.Channel - */ -static void -gabble_call_channel_get_channel_type (TpSvcChannel *iface, - DBusGMethodInvocation *context) -{ - tp_svc_channel_return_from_get_channel_type (context, - GABBLE_IFACE_CHANNEL_TYPE_CALL); -} - -/** - * gabble_call_channel_get_handle - * - * Implements D-Bus method GetHandle - * on interface org.freedesktop.Telepathy.Channel - */ -static void -gabble_call_channel_get_handle (TpSvcChannel *iface, - DBusGMethodInvocation *context) -{ - tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_CONTACT, - GABBLE_CALL_CHANNEL (iface)->priv->target); -} - -/** - * gabble_call_channel_get_interfaces - * - * Implements D-Bus method GetInterfaces - * on interface org.freedesktop.Telepathy.Channel - */ -static void -gabble_call_channel_get_interfaces (TpSvcChannel *iface, - DBusGMethodInvocation *context) -{ - tp_svc_channel_return_from_get_interfaces (context, - gabble_call_channel_interfaces); -} - -static void -channel_iface_init (gpointer g_iface, gpointer iface_data) -{ - TpSvcChannelClass *klass = (TpSvcChannelClass *) g_iface; - -#define IMPLEMENT(x, suffix) tp_svc_channel_implement_##x (\ - klass, gabble_call_channel_##x##suffix) - IMPLEMENT(close,_async); - IMPLEMENT(get_channel_type,); - IMPLEMENT(get_handle,); - IMPLEMENT(get_interfaces,); -#undef IMPLEMENT -} - -static void -gabble_call_channel_ringing (GabbleSvcChannelTypeCall *iface, - DBusGMethodInvocation *context) -{ - GabbleCallChannel *self = GABBLE_CALL_CHANNEL (iface); - GabbleCallChannelPrivate *priv = self->priv; - - if (priv->requested) - { - 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 != GABBLE_CALL_STATE_PENDING_RECEIVER) - { - 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 & GABBLE_CALL_FLAG_LOCALLY_RINGING) == 0) - { - DEBUG ("Client is ringing"); - priv->flags |= GABBLE_CALL_FLAG_LOCALLY_RINGING; - emit_call_state_changed (self); - } - - gabble_svc_channel_type_call_return_from_ringing (context); - } -} - -static void -gabble_call_channel_accept (GabbleSvcChannelTypeCall *iface, - DBusGMethodInvocation *context) -{ - GabbleCallChannel *self = GABBLE_CALL_CHANNEL (iface); - GabbleCallChannelPrivate *priv = self->priv; - - DEBUG ("Client accepted the call"); - - if (priv->requested) - { - if (priv->state == GABBLE_CALL_STATE_PENDING_INITIATOR) - { - priv->state = GABBLE_CALL_STATE_PENDING_RECEIVER; - emit_call_state_changed (self); - } - else - { - DEBUG ("Invalid state for Accept: Channel requested and " - "state == %d", priv->state); - goto err; - } - } - else if (priv->state < GABBLE_CALL_STATE_ACCEPTED) - { - priv->state = GABBLE_CALL_STATE_ACCEPTED; - emit_call_state_changed (self); - } - else - { - DEBUG ("Invalid state for Accept: state == %d", priv->state); - goto err; - } - - gabble_jingle_session_accept (self->priv->session); - g_list_foreach (self->priv->contents, - (GFunc)gabble_call_content_accept, NULL); - - gabble_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); - } -} - -static void -gabble_call_channel_hangup (GabbleSvcChannelTypeCall *iface, - guint reason, - const gchar *detailed_reason, - const gchar *message, - DBusGMethodInvocation *context) -{ - GabbleCallChannel *self = GABBLE_CALL_CHANNEL (iface); - GabbleCallChannelPrivate *priv = self->priv; - GError *error = NULL; - - if (!gabble_jingle_session_terminate (priv->session, - TP_CHANNEL_GROUP_CHANGE_REASON_NONE, - message, &error)) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - gabble_svc_channel_type_call_return_from_hangup (context); -} - -static void -gabble_call_channel_add_content (GabbleSvcChannelTypeCall *iface, - const gchar *name, - TpMediaStreamType mtype, - DBusGMethodInvocation *context) -{ - GabbleCallChannel *self = GABBLE_CALL_CHANNEL (iface); - JingleMediaType type = JINGLE_MEDIA_TYPE_NONE; - const char *path; - GError *error = NULL; - - if (self->priv->state == GABBLE_CALL_STATE_ENDED) - { - g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE, - "No contents can be added. The call has already ended."); - dbus_g_method_return_error (context, error); - return; - } - - if (mtype == TP_MEDIA_STREAM_TYPE_AUDIO) - type = JINGLE_MEDIA_TYPE_AUDIO; - else if (mtype == TP_MEDIA_STREAM_TYPE_VIDEO) - type = JINGLE_MEDIA_TYPE_VIDEO; - else - goto unicorns; - - path = call_channel_create_content (self, name, type, - GABBLE_CALL_CONTENT_DISPOSITION_NONE, &error); - - if (path == NULL) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - gabble_svc_channel_type_call_emit_content_added (self, path, type); - - gabble_svc_channel_type_call_return_from_add_content (context, path); - return; - -unicorns: - { - GError e = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, "Unknown content type" }; - dbus_g_method_return_error (context, &e); - } -} - - -static void -call_iface_init (gpointer g_iface, gpointer iface_data) -{ - GabbleSvcChannelTypeCallClass *klass = - (GabbleSvcChannelTypeCallClass *) g_iface; - -#define IMPLEMENT(x) gabble_svc_channel_type_call_implement_##x (\ - klass, gabble_call_channel_##x) - IMPLEMENT(ringing); - IMPLEMENT(accept); - IMPLEMENT(hangup); - IMPLEMENT(add_content); -#undef IMPLEMENT -} - - -static void -remote_state_changed_cb (GabbleJingleSession *session, gpointer user_data) -{ - GabbleCallChannel *self = GABBLE_CALL_CHANNEL (user_data); - GabbleCallChannelPrivate *priv = self->priv; - GabbleCallMemberFlags oldflags, newflags = 0; - GArray *empty; - - if (gabble_jingle_session_get_remote_ringing (priv->session)) - newflags |= GABBLE_CALL_MEMBER_FLAG_RINGING; - - if (gabble_jingle_session_get_remote_hold (priv->session)) - newflags |= GABBLE_CALL_MEMBER_FLAG_HELD; - - oldflags = GPOINTER_TO_UINT (g_hash_table_lookup (priv->members, - GUINT_TO_POINTER (priv->target))); - - if (oldflags == newflags) - return; - - g_hash_table_insert (priv->members, GUINT_TO_POINTER (priv->target), - GUINT_TO_POINTER (newflags)); - - empty = g_array_new (TRUE, TRUE, sizeof (TpHandle)); - gabble_svc_channel_type_call_emit_call_members_changed (self, - priv->members, empty); - g_array_unref (empty); -} - - -static void call_channel_init_async (GAsyncInitable *initable, int priority, GCancellable *cancellable, @@ -1082,25 +159,26 @@ call_channel_init_async (GAsyncInitable *initable, gpointer user_data) { GabbleCallChannel *self = GABBLE_CALL_CHANNEL (initable); - GabbleCallChannelPrivate *priv = self->priv; + GabbleBaseCallChannel *base = GABBLE_BASE_CALL_CHANNEL (self); GSimpleAsyncResult *result; result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, NULL); - if (priv->registered) + if (gabble_base_call_channel_registered (base)) goto out; - if (priv->session == NULL) + if (gabble_base_call_channel_get_session (base) == NULL) { const gchar *resource; JingleDialect dialect; + GabbleJingleSession *session; const gchar *transport; /* FIXME might need to wait on capabilities, also don't need transport * and dialect already */ - if (!jingle_pick_best_resource (priv->conn, - priv->target, priv->initial_audio, priv->initial_video, + if (!jingle_pick_best_resource (base->conn, + base->target, base->initial_audio, base->initial_video, &transport, &dialect, &resource)) { g_simple_async_result_set_error (result, TP_ERRORS, @@ -1109,31 +187,28 @@ call_channel_init_async (GAsyncInitable *initable, goto out; } - priv->transport_ns = g_strdup (transport); - priv->session = gabble_jingle_factory_create_session ( - priv->conn->jingle_factory, priv->target, resource, FALSE); + gabble_base_call_channel_set_transport (base, transport); - gabble_signal_connect_weak (priv->session, "notify::state", - G_CALLBACK (call_session_state_changed_cb), G_OBJECT (self)); - gabble_signal_connect_weak (priv->session, "new-content", - G_CALLBACK (call_session_new_content_cb), G_OBJECT (self)); + session = gabble_jingle_factory_create_session ( + base->conn->jingle_factory, base->target, resource, FALSE); + g_object_set (session, "dialect", dialect, NULL); - g_object_set (priv->session, "dialect", dialect, NULL); + gabble_base_call_channel_set_session (base, session); + g_object_unref (session); /* Setup the session and the initial contents */ - if (priv->initial_audio) - call_channel_create_content (self, "Audio", JINGLE_MEDIA_TYPE_AUDIO, + if (base->initial_audio) + gabble_base_call_channel_create_content (base, "Audio", + JINGLE_MEDIA_TYPE_AUDIO, GABBLE_CALL_CONTENT_DISPOSITION_INITIAL, NULL); - if (priv->initial_video) - call_channel_create_content (self, "Video", JINGLE_MEDIA_TYPE_VIDEO, + if (base->initial_video) + gabble_base_call_channel_create_content (base, "Video", + JINGLE_MEDIA_TYPE_VIDEO, GABBLE_CALL_CONTENT_DISPOSITION_INITIAL, NULL); } - call_channel_setup (self); - - gabble_signal_connect_weak (priv->session, "remote-state-changed", - G_CALLBACK (remote_state_changed_cb), G_OBJECT (self)); + gabble_base_call_channel_register (base); out: g_simple_async_result_complete_in_idle (result); |