diff options
author | Mikhail Zabaluev <mikhail.zabaluev@nokia.com> | 2008-04-04 15:20:21 +0000 |
---|---|---|
committer | Mikhail Zabaluev <mikhail.zabaluev@nokia.com> | 2008-04-04 15:20:21 +0000 |
commit | b10fe314452cb3cb6e076fef269e77f6ddeea730 (patch) | |
tree | 77e8924be48830d1b86e882b84f55845308dab1d | |
parent | 8949826f048c6e75427940e2fbe4353613de5dd2 (diff) |
Updated the media channel implementation to the reworked Hold and CallState APIs as of 0.17.3.1.
The CallState interface helpers are provided by telepathy-glib as of 0.7.6.
This patch does not implement the specified behavior for local hold.
20080404152021-5b6ca-666f266095e8b6765e1f8917b26a8cf42292aa3c.gz
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/sip-media-channel.c | 82 | ||||
-rw-r--r-- | src/sip-media-channel.h | 6 | ||||
-rw-r--r-- | src/sip-media-session.c | 61 | ||||
-rw-r--r-- | src/sip-media-session.h | 4 | ||||
-rw-r--r-- | tpsip-extensions/Channel_Interface_Call_State.xml | 99 | ||||
-rw-r--r-- | tpsip-extensions/Makefile.am | 1 | ||||
-rw-r--r-- | tpsip-extensions/channel.xml | 1 |
8 files changed, 90 insertions, 166 deletions
diff --git a/configure.ac b/configure.ac index dd7a5a1..39e19a8 100644 --- a/configure.ac +++ b/configure.ac @@ -97,7 +97,7 @@ AC_SUBST(SOFIA_SIP_UA_CFLAGS) AC_SUBST(SOFIA_SIP_UA_VERSION) dnl Check for telepathy-glib -PKG_CHECK_MODULES(TELEPATHY_GLIB, [telepathy-glib >= 0.7.3]) +PKG_CHECK_MODULES(TELEPATHY_GLIB, [telepathy-glib >= 0.7.6]) AC_SUBST(TELEPATHY_GLIB_CFLAGS) AC_SUBST(TELEPATHY_GLIB_LIBS) diff --git a/src/sip-media-channel.c b/src/sip-media-channel.c index 05b11ff..03030b3 100644 --- a/src/sip-media-channel.c +++ b/src/sip-media-channel.c @@ -36,7 +36,7 @@ #include <tpsip/event-target.h> -/* Hold and CallState interfaces */ +/* Hold interface */ #include <tpsip-extensions/extensions.h> #include "sip-media-channel.h" @@ -68,7 +68,7 @@ G_DEFINE_TYPE_WITH_CODE (TpsipMediaChannel, tpsip_media_channel, media_signalling_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_DTMF, dtmf_iface_init); - G_IMPLEMENT_INTERFACE (TPSIP_TYPE_SVC_CHANNEL_INTERFACE_CALL_STATE, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_CALL_STATE, call_state_iface_init); G_IMPLEMENT_INTERFACE (TPSIP_TYPE_SVC_CHANNEL_INTERFACE_HOLD, hold_iface_init); @@ -535,7 +535,7 @@ tpsip_media_channel_get_interfaces (TpSvcChannel *iface, TP_IFACE_CHANNEL_INTERFACE_GROUP, TP_IFACE_CHANNEL_INTERFACE_MEDIA_SIGNALLING, TP_IFACE_CHANNEL_INTERFACE_DTMF, - TPSIP_IFACE_CHANNEL_INTERFACE_CALL_STATE, + TP_IFACE_CHANNEL_INTERFACE_CALL_STATE, TPSIP_IFACE_CHANNEL_INTERFACE_HOLD, TP_IFACE_PROPERTIES_INTERFACE, NULL @@ -908,34 +908,37 @@ tpsip_media_channel_peer_error (TpsipMediaChannel *self, tp_intset_destroy (set); } -static void -priv_set_call_state (TpsipMediaChannel *self, - TpHandle peer, - guint flags) +guint +tpsip_media_channel_change_call_state (TpsipMediaChannel *self, + TpHandle peer, + guint flags_add, + guint flags_remove) { TpsipMediaChannelPrivate *priv = TPSIP_MEDIA_CHANNEL_GET_PRIVATE (self); + gpointer key = GUINT_TO_POINTER (peer); + guint old_state; + guint new_state; - DEBUG ("setting call state %u for peer %u", flags, peer); - g_hash_table_replace (priv->call_states, - GUINT_TO_POINTER (peer), - GUINT_TO_POINTER (flags)); - tpsip_svc_channel_interface_call_state_emit_call_state_changed (self, - peer, - flags); -} + /* XXX: check if the peer is a member? */ -static void -priv_clear_call_state (TpsipMediaChannel *self, - TpHandle peer) -{ - TpsipMediaChannelPrivate *priv = TPSIP_MEDIA_CHANNEL_GET_PRIVATE (self); + old_state = GPOINTER_TO_UINT (g_hash_table_lookup (priv->call_states, key)); + new_state = (old_state | flags_add) & ~flags_remove; - DEBUG ("clearing call state for peer %u", peer); - if (g_hash_table_remove (priv->call_states, - GUINT_TO_POINTER (peer))) - tpsip_svc_channel_interface_call_state_emit_call_state_changed (self, - peer, - 0); + if (new_state != old_state) + { + DEBUG ("setting call state %u for peer %u", new_state, peer); + if (new_state == 0) + g_hash_table_remove (priv->call_states, key); + else + g_hash_table_replace (priv->call_states, key, + GUINT_TO_POINTER (new_state)); + + tp_svc_channel_interface_call_state_emit_call_state_changed (self, + peer, + new_state); + } + + return new_state; } static gboolean @@ -962,19 +965,23 @@ priv_nua_r_invite_cb (TpsipMediaChannel *self, if (status >= 200) { - /* The final response, clear the Ringing call state flag if set */ - priv_clear_call_state (self, peer); + /* The final response, clear the Ringing and Queued call state flags */ + tpsip_media_channel_change_call_state (self, peer, 0, + TP_CHANNEL_CALL_STATE_RINGING | + TP_CHANNEL_CALL_STATE_QUEUED); if (status >= 300) tpsip_media_channel_peer_error (self, peer, status, message); } else if (status == 180) { - priv_set_call_state (self, peer, TPSIP_CHANNEL_CALL_STATE_RINGING); + tpsip_media_channel_change_call_state (self, peer, + TP_CHANNEL_CALL_STATE_RINGING, 0); } else if (status == 182) { - priv_set_call_state (self, peer, TPSIP_CHANNEL_CALL_STATE_QUEUED); + tpsip_media_channel_change_call_state (self, peer, + TP_CHANNEL_CALL_STATE_QUEUED, 0); } return TRUE; @@ -1502,20 +1509,20 @@ tpsip_media_channel_remove_with_reason (GObject *obj, } static void -tpsip_media_channel_get_call_states (TpsipSvcChannelInterfaceCallState *iface, - DBusGMethodInvocation *context) +tpsip_media_channel_get_call_states (TpSvcChannelInterfaceCallState *iface, + DBusGMethodInvocation *context) { TpsipMediaChannel *self = TPSIP_MEDIA_CHANNEL (iface); TpsipMediaChannelPrivate *priv = TPSIP_MEDIA_CHANNEL_GET_PRIVATE (self); - tpsip_svc_channel_interface_call_state_return_from_get_call_states ( + tp_svc_channel_interface_call_state_return_from_get_call_states ( context, priv->call_states); } static void tpsip_media_channel_get_hold_state (TpsipSvcChannelInterfaceHold *iface, - DBusGMethodInvocation *context) + DBusGMethodInvocation *context) { TpsipMediaChannel *self = TPSIP_MEDIA_CHANNEL (iface); TpsipMediaChannelPrivate *priv = TPSIP_MEDIA_CHANNEL_GET_PRIVATE (self); @@ -1523,7 +1530,8 @@ tpsip_media_channel_get_hold_state (TpsipSvcChannelInterfaceHold *iface, tpsip_svc_channel_interface_hold_return_from_get_hold_state (context, (priv->session != NULL) ? tpsip_media_session_get_hold_state (priv->session) - : TPSIP_CHANNEL_HOLD_STATE_NONE); + : TPSIP_LOCAL_HOLD_STATE_UNHELD, + TPSIP_LOCAL_HOLD_STATE_REASON_NONE); } static void @@ -1692,8 +1700,8 @@ static void call_state_iface_init (gpointer g_iface, gpointer iface_data) { - TpsipSvcChannelInterfaceCallStateClass *klass = g_iface; -#define IMPLEMENT(x) tpsip_svc_channel_interface_call_state_implement_##x (\ + TpSvcChannelInterfaceCallStateClass *klass = g_iface; +#define IMPLEMENT(x) tp_svc_channel_interface_call_state_implement_##x (\ klass, tpsip_media_channel_##x) IMPLEMENT (get_call_states); #undef IMPLEMENT diff --git a/src/sip-media-channel.h b/src/sip-media-channel.h index 8aae83a..42fba02 100644 --- a/src/sip-media-channel.h +++ b/src/sip-media-channel.h @@ -75,6 +75,12 @@ void tpsip_media_channel_receive_invite (TpsipMediaChannel *self, nua_handle_t *nh, TpHandle handle); +guint +tpsip_media_channel_change_call_state (TpsipMediaChannel *self, + TpHandle peer, + guint flags_add, + guint flags_remove); + G_END_DECLS #endif /* #ifndef __TPSIP_MEDIA_CHANNEL_H__*/ diff --git a/src/sip-media-session.c b/src/sip-media-session.c index 1a2d8b9..285c2ca 100644 --- a/src/sip-media-session.c +++ b/src/sip-media-session.c @@ -117,8 +117,8 @@ struct _TpsipMediaSessionPrivate nua_handle_t *nua_op; /** see gobj. prop. 'nua-handle' */ TpHandle peer; /** see gobj. prop. 'peer' */ gchar *local_ip_address; /** see gobj. prop. 'local-ip-address' */ - TpsipMediaSessionState state; /** session state */ - TpsipChannelHoldState hold_state; /** hold state aggregated from stream directions */ + TpsipMediaSessionState state; /** session state */ + TpsipLocalHoldState hold_state; /** local hold state aggregated from stream directions */ nua_saved_event_t saved_event[1]; /** Saved incoming request event */ gint local_non_ready; /** number of streams with local information update pending */ guint remote_stream_count; /** number of streams last seen in a remote offer */ @@ -170,7 +170,7 @@ static void tpsip_media_session_init (TpsipMediaSession *obj) priv->state = TPSIP_MEDIA_SESSION_STATE_CREATED; - priv->hold_state = TPSIP_CHANNEL_HOLD_STATE_NONE; + priv->hold_state = TPSIP_LOCAL_HOLD_STATE_UNHELD; /* allocate any data required by the object here */ priv->streams = g_ptr_array_new (); @@ -1104,13 +1104,21 @@ tpsip_media_session_get_stream (TpsipMediaSession *self, return stream; } -TpsipChannelHoldState +TpsipLocalHoldState tpsip_media_session_get_hold_state (TpsipMediaSession *self) { TpsipMediaSessionPrivate *priv = TPSIP_MEDIA_SESSION_GET_PRIVATE (self); return priv->hold_state; } +static gboolean +tpsip_media_session_is_local_hold_ongoing (TpsipMediaSession *self) +{ + TpsipMediaSessionPrivate *priv = TPSIP_MEDIA_SESSION_GET_PRIVATE (self); + return (priv->hold_state == TPSIP_LOCAL_HOLD_STATE_HELD + || priv->hold_state == TPSIP_LOCAL_HOLD_STATE_PENDING_HOLD); +} + void tpsip_media_session_request_hold (TpsipMediaSession *self, gboolean hold) @@ -1278,16 +1286,15 @@ priv_local_media_changed (TpsipMediaSession *session) } static void -priv_update_hold_state (TpsipMediaSession *session) +priv_update_remote_hold (TpsipMediaSession *session) { TpsipMediaSessionPrivate *priv = TPSIP_MEDIA_SESSION_GET_PRIVATE (session); TpsipMediaStream *stream; gboolean has_streams = FALSE; - guint hold_state = TPSIP_CHANNEL_HOLD_STATE_BOTH; + gboolean remote_held = TRUE; guint i; - /* Starting with bidirectional hold, bid down accordingly to availability - * of streams unheld localy or remotely */ + /* The call is remotely unheld if there's at least one sending stream */ for (i = 0; i < priv->streams->len; i++) { stream = g_ptr_array_index(priv->streams, i); @@ -1299,21 +1306,25 @@ priv_update_hold_state (TpsipMediaSession *session) NULL); if ((direction & TP_MEDIA_STREAM_DIRECTION_SEND) != 0) - hold_state &= ~TPSIP_CHANNEL_HOLD_STATE_REMOTE; - if ((direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE) != 0) - hold_state &= ~TPSIP_CHANNEL_HOLD_STATE_LOCAL; + remote_held = FALSE; has_streams = TRUE; } } - if (has_streams && priv->hold_state != hold_state) - { - DEBUG("changing hold state to %u", hold_state); - priv->hold_state = hold_state; - tpsip_svc_channel_interface_hold_emit_hold_state_changed (priv->channel, - priv->hold_state); - } + if (!has_streams) + return; + + if (remote_held) + tpsip_media_channel_change_call_state (priv->channel, + priv->peer, + TP_CHANNEL_CALL_STATE_HELD, + 0); + else + tpsip_media_channel_change_call_state (priv->channel, + priv->peer, + 0, + TP_CHANNEL_CALL_STATE_HELD); } static gboolean @@ -1334,9 +1345,9 @@ priv_update_remote_media (TpsipMediaSession *session, gboolean authoritative) */ if (authoritative) direction_up_mask - = ((priv->hold_state & TPSIP_CHANNEL_HOLD_STATE_LOCAL) == 0) - ? TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL - : TP_MEDIA_STREAM_DIRECTION_SEND; + = tpsip_media_session_is_local_hold_ongoing (session) + ? TP_MEDIA_STREAM_DIRECTION_SEND + : TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL; else direction_up_mask = 0; @@ -1422,7 +1433,7 @@ priv_update_remote_media (TpsipMediaSession *session, gboolean authoritative) } if (has_supported_media) - priv_update_hold_state (session); + priv_update_remote_hold (session); DEBUG("exit"); @@ -1793,9 +1804,9 @@ priv_create_media_stream (TpsipMediaSession *self, priv->object_path, stream_id); - direction = ((priv->hold_state & TPSIP_CHANNEL_HOLD_STATE_LOCAL) == 0) - ? TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL - : TP_MEDIA_STREAM_DIRECTION_SEND; + direction = tpsip_media_session_is_local_hold_ongoing (self) + ? TP_MEDIA_STREAM_DIRECTION_SEND + : TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL; stream = g_object_new (TPSIP_TYPE_MEDIA_STREAM, "media-session", self, diff --git a/src/sip-media-session.h b/src/sip-media-session.h index 082a594..c8fe31e 100644 --- a/src/sip-media-session.h +++ b/src/sip-media-session.h @@ -99,9 +99,9 @@ void tpsip_media_session_reject (TpsipMediaSession *self, gint status, const char *message); -TpsipChannelHoldState tpsip_media_session_get_hold_state (TpsipMediaSession *session); +TpsipLocalHoldState tpsip_media_session_get_hold_state (TpsipMediaSession *session); void tpsip_media_session_request_hold (TpsipMediaSession *session, - gboolean hold); + gboolean hold); gboolean tpsip_media_session_start_telephony_event (TpsipMediaSession *self, guint stream_id, diff --git a/tpsip-extensions/Channel_Interface_Call_State.xml b/tpsip-extensions/Channel_Interface_Call_State.xml deleted file mode 100644 index b0faa42..0000000 --- a/tpsip-extensions/Channel_Interface_Call_State.xml +++ /dev/null @@ -1,99 +0,0 @@ -<?xml version="1.0" ?> -<node name="/Channel_Interface_Call_State" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> - <tp:copyright> Copyright (C) 2008 Collabora Limited </tp:copyright> - <tp:copyright> Copyright (C) 2008 Nokia Corporation </tp:copyright> - <tp:license xmlns="http://www.w3.org/1999/xhtml"> - <p>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.</p> - -<p>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.</p> - -<p>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 Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> - </tp:license> - <interface name="org.freedesktop.Telepathy.Channel.Interface.CallState"> - <tp:requires interface="org.freedesktop.Telepathy.Channel.Type.StreamedMedia"/> - - <tp:docstring> - An interface for streamed media channels that can indicate call - progress or call states. The presence of this interface is no guarantee - that call states will actually be signalled (for instance, SIP - implementations are not guaranteed to generate status 180 Ringing, - so a call can be accepted without the Ringing flag ever having been set). - </tp:docstring> - - <method name="GetCallStates"> - <tp:docstring> - Get the current call states for all contacts involved in this call. - </tp:docstring> - - <arg tp:type="Channel_Call_State_Map" name="States" direction="out" - type="a{uu}"> - <tp:docstring> - The current call states. Participants where the call state flags - would be 0 (all unset) may be omitted from this mapping. - </tp:docstring> - </arg> - </method> - - <signal name="CallStateChanged"> - <tp:docstring> - Emitted when the state of a member of the channel has changed. - </tp:docstring> - - <arg name="contact" type="u" tp:type="Contact_Handle"> - <tp:docstring> - An integer handle for the contact. - </tp:docstring> - </arg> - - <arg name="state" type="u" tp:type="Channel_Call_State_Flags"> - <tp:docstring> - The new state for this contact. - </tp:docstring> - </arg> - </signal> - - <tp:mapping name="Channel_Call_State_Map"> - <tp:docstring> - A map from contacts to call states. - </tp:docstring> - - <tp:member name="Contact" type="u" tp:type="Contact_Handle"> - <tp:docstring>A contact involved in this call.</tp:docstring> - </tp:member> - - <tp:member name="State" type="u" tp:type="Channel_Call_State_Flags"> - <tp:docstring>State flags for the given contact.</tp:docstring> - </tp:member> - </tp:mapping> - - <tp:flags name="Channel_Call_State_Flags" value-prefix="Channel_Call_State" type="u"> - <tp:docstring> - A set of flags representing call states. - </tp:docstring> - - <tp:flag suffix="Ringing" value="1"> - <tp:docstring> - The contact has been alerted about the call but has not responded - (e.g. 180 Ringing in SIP). - </tp:docstring> - </tp:flag> - - <tp:flag suffix="Queued" value="2"> - <tp:docstring> - The contact is temporarily unavailable, and the call has been placed - in a queue (e.g. 182 Queued in SIP, or call-waiting in telephony). - </tp:docstring> - </tp:flag> - </tp:flags> - - </interface> -</node> -<!-- vim:set sw=2 sts=2 et ft=xml: --> diff --git a/tpsip-extensions/Makefile.am b/tpsip-extensions/Makefile.am index 0e8190d..356f381 100644 --- a/tpsip-extensions/Makefile.am +++ b/tpsip-extensions/Makefile.am @@ -9,7 +9,6 @@ AM_CFLAGS = \ EXTRA_DIST = \ all.xml \ channel.xml \ - Channel_Interface_Call_State.xml \ Channel_Interface_Hold.xml noinst_LTLIBRARIES = libtpsip-extensions.la diff --git a/tpsip-extensions/channel.xml b/tpsip-extensions/channel.xml index 84abb22..d8ecf19 100644 --- a/tpsip-extensions/channel.xml +++ b/tpsip-extensions/channel.xml @@ -4,7 +4,6 @@ <tp:title>Channel extensions for telepathy-sofiasip</tp:title> -<xi:include href="Channel_Interface_Call_State.xml"/> <xi:include href="Channel_Interface_Hold.xml"/> </tp:spec> |