From 00cee1f4be989644d757bb99fe178b1ad5ada9ba Mon Sep 17 00:00:00 2001 From: Jakub Adam Date: Sun, 6 Jan 2013 22:19:40 +0100 Subject: [PATCH] media: Farstream 0.1.1 compatibility fix Because of change in Farstream, purple_media_get_codecs() can return NULL until any needed codec configuration parameters have been discovered. As a consequence we have to wait until both local candidates and codec parameters are gathered before firing sipe_media_call->candidates_prepared_cb(). Also some functions and fields were renamed to better depict their purpose: * sipe_media_call->candidates_prepared_cb to sipe_media_call->stream_initialized_cb * candidates_prepared_cb() to stream_initialized_cb() * sipe_backend_candidates_prepared() to sipe_backend_stream_initialized() and gets new sipe_backend_stream * argument This fixes broken video calls. --- src/api/sipe-backend.h | 7 +++--- src/core/sipe-media.c | 52 +++++++++++++++++++++++++++-------------- src/miranda/miranda-media.c | 3 ++- src/purple/purple-media.c | 47 ++++++++++++++++++++++++++++++------- src/telepathy/telepathy-stubs.c | 3 ++- 5 files changed, 82 insertions(+), 30 deletions(-) diff --git a/src/api/sipe-backend.h b/src/api/sipe-backend.h index 95fbc900..27db9639 100644 --- a/src/api/sipe-backend.h +++ b/src/api/sipe-backend.h @@ -350,8 +350,8 @@ struct sipe_backend_media_relays; struct sipe_media_call { struct sipe_backend_media *backend_private; - void (*candidates_prepared_cb)(struct sipe_media_call *, - struct sipe_backend_stream *); + void (*stream_initialized_cb)(struct sipe_media_call *, + struct sipe_backend_stream *); void (*media_end_cb)(struct sipe_media_call *); void (*call_accept_cb)(struct sipe_media_call *, gboolean local); void (*call_reject_cb)(struct sipe_media_call *, gboolean local); @@ -400,7 +400,8 @@ void sipe_backend_media_add_remote_candidates(struct sipe_backend_media *media, gboolean sipe_backend_media_is_initiator(struct sipe_backend_media *media, struct sipe_backend_stream *stream); gboolean sipe_backend_media_accepted(struct sipe_backend_media *media); -gboolean sipe_backend_candidates_prepared(struct sipe_backend_media *media); +gboolean sipe_backend_stream_initialized(struct sipe_backend_media *media, + struct sipe_backend_stream *stream); GList *sipe_backend_media_get_active_local_candidates(struct sipe_backend_media *media, struct sipe_backend_stream *stream); GList *sipe_backend_media_get_active_remote_candidates(struct sipe_backend_media *media, diff --git a/src/core/sipe-media.c b/src/core/sipe-media.c index 507a2bdb..d1ab7785 100644 --- a/src/core/sipe-media.c +++ b/src/core/sipe-media.c @@ -511,6 +511,22 @@ apply_remote_message(struct sipe_media_call_private* call_private, call_private->encryption_compatible = encryption_levels_compatible(msg); } +static gboolean +call_initialized(struct sipe_media_call *call) +{ + GSList *streams = + sipe_backend_media_get_streams(call->backend_private); + + for (; streams; streams = streams->next) { + if (!sipe_backend_stream_initialized(call->backend_private, + streams->data)) { + return FALSE; + } + } + + return TRUE; +} + // Sends an invite response when the call is accepted and local candidates were // prepared, otherwise does nothing. If error response is sent, call_private is // disposed before function returns. Returns true when response was sent. @@ -522,7 +538,7 @@ send_invite_response_if_ready(struct sipe_media_call_private *call_private) backend_media = call_private->public.backend_private; if (!sipe_backend_media_accepted(backend_media) || - !sipe_backend_candidates_prepared(backend_media)) + !call_initialized(&call_private->public)) return FALSE; if (!call_private->encryption_compatible) { @@ -546,22 +562,24 @@ send_invite_response_if_ready(struct sipe_media_call_private *call_private) } static void -candidates_prepared_cb(struct sipe_media_call *call, - struct sipe_backend_stream *stream) +stream_initialized_cb(struct sipe_media_call *call, + struct sipe_backend_stream *stream) { - struct sipe_media_call_private *call_private = SIPE_MEDIA_CALL_PRIVATE; - struct sipe_backend_media *backend_private = call->backend_private; - - if (sipe_backend_media_is_initiator(backend_private, stream)) { - sipe_invite_call(call_private->sipe_private, - process_invite_call_response); - } else { - struct sdpmsg *smsg = call_private->smsg; - call_private->smsg = NULL; - - apply_remote_message(call_private, smsg); - send_invite_response_if_ready(call_private); - sdpmsg_free(smsg); + if (call_initialized(call)) { + struct sipe_media_call_private *call_private = SIPE_MEDIA_CALL_PRIVATE; + struct sipe_backend_media *backend_private = call->backend_private; + + if (sipe_backend_media_is_initiator(backend_private, stream)) { + sipe_invite_call(call_private->sipe_private, + process_invite_call_response); + } else if (call_private->smsg) { + struct sdpmsg *smsg = call_private->smsg; + call_private->smsg = NULL; + + apply_remote_message(call_private, smsg); + send_invite_response_if_ready(call_private); + sdpmsg_free(smsg); + } } } @@ -673,7 +691,7 @@ sipe_media_call_new(struct sipe_core_private *sipe_private, call_private->ice_version = ice_version; call_private->encryption_compatible = TRUE; - call_private->public.candidates_prepared_cb = candidates_prepared_cb; + call_private->public.stream_initialized_cb = stream_initialized_cb; call_private->public.media_end_cb = media_end_cb; call_private->public.call_accept_cb = call_accept_cb; call_private->public.call_reject_cb = call_reject_cb; diff --git a/src/miranda/miranda-media.c b/src/miranda/miranda-media.c index c4a5b7e5..3eeb8aa8 100644 --- a/src/miranda/miranda-media.c +++ b/src/miranda/miranda-media.c @@ -134,7 +134,8 @@ gboolean sipe_backend_media_accepted(struct sipe_backend_media *media) } gboolean -sipe_backend_candidates_prepared(struct sipe_backend_media *media) +sipe_backend_stream_initialized(struct sipe_backend_media *media, + struct sipe_backend_stream *stream) { _NIF(); return FALSE; diff --git a/src/purple/purple-media.c b/src/purple/purple-media.c index 62f22a44..cff5d5cb 100644 --- a/src/purple/purple-media.c +++ b/src/purple/purple-media.c @@ -94,18 +94,33 @@ static PurpleMediaNetworkProtocol sipe_network_protocol_to_purple(SipeNetworkPro static SipeNetworkProtocol purple_network_protocol_to_sipe(PurpleMediaNetworkProtocol proto); static void +maybe_signal_stream_initialized(struct sipe_media_call *call, gchar *sessionid) +{ + if (call->stream_initialized_cb) { + struct sipe_backend_stream *stream; + stream = sipe_backend_media_get_stream_by_id(call->backend_private, sessionid); + + if (sipe_backend_stream_initialized(call->backend_private, stream)) { + call->stream_initialized_cb(call, stream); + } + } +} + +static void on_candidates_prepared_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media, gchar *sessionid, SIPE_UNUSED_PARAMETER gchar *participant, struct sipe_media_call *call) { - struct sipe_backend_stream *stream; - stream = sipe_backend_media_get_stream_by_id(call->backend_private, sessionid); + maybe_signal_stream_initialized(call, sessionid); +} - if (call->candidates_prepared_cb && - sipe_backend_candidates_prepared(call->backend_private)) { - call->candidates_prepared_cb(call, stream); - } +static void +on_codecs_changed_cb(SIPE_UNUSED_PARAMETER PurpleMedia *media, + gchar *sessionid, + struct sipe_media_call *call) +{ + maybe_signal_stream_initialized(call, sessionid); } static void @@ -228,6 +243,8 @@ sipe_backend_media_new(struct sipe_core_public *sipe_public, g_signal_connect(G_OBJECT(media->m), "candidates-prepared", G_CALLBACK(on_candidates_prepared_cb), call); + g_signal_connect(G_OBJECT(media->m), "codecs-changed", + G_CALLBACK(on_codecs_changed_cb), call); g_signal_connect(G_OBJECT(media->m), "stream-info", G_CALLBACK(on_stream_info_cb), call); g_signal_connect(G_OBJECT(media->m), "error", @@ -533,9 +550,23 @@ gboolean sipe_backend_media_accepted(struct sipe_backend_media *media) } gboolean -sipe_backend_candidates_prepared(struct sipe_backend_media *media) +sipe_backend_stream_initialized(struct sipe_backend_media *media, + struct sipe_backend_stream *stream) { - return purple_media_candidates_prepared(media->m, NULL, NULL); + g_return_val_if_fail(media, FALSE); + g_return_val_if_fail(stream, FALSE); + + if (purple_media_candidates_prepared(media->m, + stream->sessionid, + stream->participant)) { + GList *codecs; + codecs = purple_media_get_codecs(media->m, stream->sessionid); + if (codecs) { + purple_media_codec_list_free(codecs); + return TRUE; + } + } + return FALSE; } GList * diff --git a/src/telepathy/telepathy-stubs.c b/src/telepathy/telepathy-stubs.c index e89b7c1d..9e6f90a5 100644 --- a/src/telepathy/telepathy-stubs.c +++ b/src/telepathy/telepathy-stubs.c @@ -194,7 +194,8 @@ void sipe_backend_media_add_remote_candidates(SIPE_UNUSED_PARAMETER struct sipe_ gboolean sipe_backend_media_is_initiator(SIPE_UNUSED_PARAMETER struct sipe_backend_media *media, SIPE_UNUSED_PARAMETER struct sipe_backend_stream *stream) { return(FALSE); } gboolean sipe_backend_media_accepted(SIPE_UNUSED_PARAMETER struct sipe_backend_media *media) { return(FALSE); } -gboolean sipe_backend_candidates_prepared(SIPE_UNUSED_PARAMETER struct sipe_backend_media *media) { return(FALSE); } +gboolean sipe_backend_stream_initialized(SIPE_UNUSED_PARAMETER struct sipe_backend_media *media, + SIPE_UNUSED_PARAMETER struct sipe_backend_stream *stream) { return(FALSE); } GList *sipe_backend_media_get_active_local_candidates(SIPE_UNUSED_PARAMETER struct sipe_backend_media *media, SIPE_UNUSED_PARAMETER struct sipe_backend_stream *stream) { return(NULL); } GList *sipe_backend_media_get_active_remote_candidates(SIPE_UNUSED_PARAMETER struct sipe_backend_media *media, -- 2.11.4.GIT