diff options
Diffstat (limited to 'libpurple/media/backend-fs2.c')
-rw-r--r-- | libpurple/media/backend-fs2.c | 302 |
1 files changed, 212 insertions, 90 deletions
diff --git a/libpurple/media/backend-fs2.c b/libpurple/media/backend-fs2.c index 1d561bcc63..2a3774d938 100644 --- a/libpurple/media/backend-fs2.c +++ b/libpurple/media/backend-fs2.c @@ -41,6 +41,7 @@ #include <farstream/fs-conference.h> #include <farstream/fs-element-added-notifier.h> #include <farstream/fs-utils.h> +#include <gst/gststructure.h> #endif /** @copydoc _PurpleMediaBackendFs2Class */ @@ -239,9 +240,17 @@ purple_media_network_protocol_from_fs(FsNetworkProtocol protocol) g_return_val_if_reached(PURPLE_MEDIA_NETWORK_PROTOCOL_TCP); } +#if GST_CHECK_VERSION(1,0,0) +static GstPadProbeReturn +event_probe_cb(GstPad *srcpad, GstPadProbeInfo *info, gpointer unused) +#else static gboolean event_probe_cb(GstPad *srcpad, GstEvent *event, gboolean release_pad) +#endif { +#if GST_CHECK_VERSION(1,0,0) + GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info); +#endif if (GST_EVENT_TYPE(event) == GST_EVENT_CUSTOM_DOWNSTREAM && gst_event_has_name(event, "purple-unlink-tee")) { @@ -249,22 +258,40 @@ event_probe_cb(GstPad *srcpad, GstEvent *event, gboolean release_pad) gst_pad_unlink(srcpad, gst_pad_get_peer(srcpad)); +#if GST_CHECK_VERSION(1,0,0) + gst_pad_remove_probe(srcpad, + g_value_get_ulong(gst_structure_get_value(s, "handler-id"))); +#else gst_pad_remove_event_probe(srcpad, g_value_get_uint(gst_structure_get_value(s, "handler-id"))); +#endif if (g_value_get_boolean(gst_structure_get_value(s, "release-pad"))) gst_element_release_request_pad(GST_ELEMENT_PARENT(srcpad), srcpad); +#if GST_CHECK_VERSION(1,0,0) + return GST_PAD_PROBE_DROP; +#else return FALSE; +#endif } +#if GST_CHECK_VERSION(1,0,0) + return GST_PAD_PROBE_OK; +#else return TRUE; +#endif } static void unlink_teepad_dynamic(GstPad *srcpad, gboolean release_pad) { +#if GST_CHECK_VERSION(1,0,0) + gulong id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + event_probe_cb, NULL, NULL); +#else guint id = gst_pad_add_event_probe(srcpad, G_CALLBACK(event_probe_cb), NULL); +#endif if (GST_IS_GHOST_PAD(srcpad)) srcpad = gst_ghost_pad_get_target(GST_GHOST_PAD(srcpad)); @@ -273,7 +300,11 @@ unlink_teepad_dynamic(GstPad *srcpad, gboolean release_pad) gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, gst_structure_new("purple-unlink-tee", "release-pad", G_TYPE_BOOLEAN, release_pad, +#if GST_CHECK_VERSION(1,0,0) + "handler-id", G_TYPE_ULONG, id, +#else "handler-id", G_TYPE_UINT, id, +#endif NULL))); } @@ -855,15 +886,31 @@ gst_msg_db_to_percent(GstMessage *msg, gchar *value_name) gdouble value_db; gdouble percent; - list = gst_structure_get_value( - gst_message_get_structure(msg), value_name); + list = gst_structure_get_value(gst_message_get_structure(msg), value_name); +#if GST_CHECK_VERSION(1,0,0) +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + value = g_value_array_get_nth(g_value_get_boxed(list), 0); +G_GNUC_END_IGNORE_DEPRECATIONS +#else value = gst_value_list_get_value(list, 0); +#endif value_db = g_value_get_double(value); percent = pow(10, value_db / 20); return (percent > 1.0) ? 1.0 : percent; } static void +purple_media_error_fs(PurpleMedia *media, const gchar *error, + const GstStructure *fs_error) +{ + const gchar *error_msg = gst_structure_get_string(fs_error, "error-msg"); + + purple_media_error(media, "%s%s%s", error, + error_msg ? _("\n\nMessage from Farsight: ") : "", + error_msg ? error_msg : ""); +} + +static void gst_handle_message_element(GstBus *bus, GstMessage *msg, PurpleMediaBackendFs2 *self) { @@ -871,11 +918,12 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); GstElement *src = GST_ELEMENT(GST_MESSAGE_SRC(msg)); static guint level_id = 0; + const GstStructure *structure = gst_message_get_structure(msg); if (level_id == 0) level_id = g_signal_lookup("level", PURPLE_TYPE_MEDIA); - if (gst_structure_has_name(msg->structure, "level")) { + if (gst_structure_has_name(structure, "level")) { GstElement *src = GST_ELEMENT(GST_MESSAGE_SRC(msg)); gchar *name; gchar *participant = NULL; @@ -930,31 +978,63 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, return; #ifdef HAVE_FARSIGHT - if (gst_structure_has_name(msg->structure, "farsight-error")) { + if (gst_structure_has_name(structure, "farsight-error")) { #else - if (gst_structure_has_name(msg->structure, "farstream-error")) { + if (gst_structure_has_name(structure, "farstream-error")) { #endif FsError error_no; - gst_structure_get_enum(msg->structure, "error-no", + gboolean error_emitted = FALSE; + gst_structure_get_enum(structure, "error-no", FS_TYPE_ERROR, (gint*)&error_no); switch (error_no) { + case FS_ERROR_CONSTRUCTION: + purple_media_error_fs(priv->media, + _("Error initializing the call. " + "This probably denotes problem in " +#ifdef HAVE_FARSIGHT + "installation of GStreamer or Farsight."), +#else + "installation of GStreamer or Farstream."), +#endif + structure); + error_emitted = TRUE; + break; + case FS_ERROR_NETWORK: + purple_media_error_fs(priv->media, _("Network error."), + structure); + error_emitted = TRUE; + purple_media_end(priv->media, NULL, NULL); + break; + case FS_ERROR_NEGOTIATION_FAILED: + purple_media_error_fs(priv->media, + _("Codec negotiation failed. " + "This problem might be resolved by installing " + "more GStreamer codecs."), + structure); + error_emitted = TRUE; + purple_media_end(priv->media, NULL, NULL); + break; case FS_ERROR_NO_CODECS: - purple_media_error(priv->media, _("No codecs" - " found. Install some" - " GStreamer codecs found" - " in GStreamer plugins" - " packages.")); + purple_media_error(priv->media, + _("No codecs found. " + "Install some GStreamer codecs found " + "in GStreamer plugins packages.")); + error_emitted = TRUE; purple_media_end(priv->media, NULL, NULL); break; #ifdef HAVE_FARSIGHT case FS_ERROR_NO_CODECS_LEFT: - purple_media_error(priv->media, _("No codecs" - " left. Your codec" - " preferences in" - " fs-codecs.conf are too" - " strict.")); + purple_media_error(priv->media, + _("No codecs left. Your codec preferences " + "in fs-codecs.conf are too strict.")); + error_emitted = TRUE; purple_media_end(priv->media, NULL, NULL); break; + case FS_ERROR_CONNECTION_FAILED: + purple_media_error(priv->media, + _("Could not connect to the remote party")); + error_emitted = TRUE; + break; case FS_ERROR_UNKNOWN_CNAME: /* * Unknown CName is only a problem for the @@ -971,22 +1051,22 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, "farstream-error: %i: %s\n", #endif error_no, - gst_structure_get_string( - msg->structure, "error-msg")); + gst_structure_get_string(structure, "error-msg")); break; } if (FS_ERROR_IS_FATAL(error_no)) { + if (!error_emitted) #ifdef HAVE_FARSIGHT - purple_media_error(priv->media, _("A non-recoverable " - "Farsight2 error has occurred.")); + purple_media_error(priv->media, + _("A non-recoverable Farsight2 error has occurred.")); #else - purple_media_error(priv->media, _("A non-recoverable " - "Farstream error has occurred.")); + purple_media_error(priv->media, + _("A non-recoverable Farstream error has occurred.")); #endif purple_media_end(priv->media, NULL, NULL); } - } else if (gst_structure_has_name(msg->structure, + } else if (gst_structure_has_name(structure, #ifdef HAVE_FARSIGHT "farsight-new-local-candidate")) { #else @@ -1001,9 +1081,9 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, PurpleMediaBackendFs2Stream *media_stream; gchar *name; - value = gst_structure_get_value(msg->structure, "stream"); + value = gst_structure_get_value(structure, "stream"); stream = g_value_get_object(value); - value = gst_structure_get_value(msg->structure, "candidate"); + value = gst_structure_get_value(structure, "candidate"); local_candidate = g_value_get_boxed(value); session = get_session_from_fs_stream(self, stream); @@ -1025,7 +1105,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, g_signal_emit_by_name(self, "new-candidate", session->id, name, candidate); g_object_unref(candidate); - } else if (gst_structure_has_name(msg->structure, + } else if (gst_structure_has_name(structure, #ifdef HAVE_FARSIGHT "farsight-local-candidates-prepared")) { #else @@ -1037,7 +1117,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, PurpleMediaBackendFs2Session *session; gchar *name; - value = gst_structure_get_value(msg->structure, "stream"); + value = gst_structure_get_value(structure, "stream"); stream = g_value_get_object(value); session = get_session_from_fs_stream(self, stream); @@ -1047,7 +1127,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, g_signal_emit_by_name(self, "candidates-prepared", session->id, name); - } else if (gst_structure_has_name(msg->structure, + } else if (gst_structure_has_name(structure, #ifdef HAVE_FARSIGHT "farsight-new-active-candidate-pair")) { #else @@ -1062,13 +1142,11 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, PurpleMediaCandidate *lcandidate, *rcandidate; gchar *name; - value = gst_structure_get_value(msg->structure, "stream"); + value = gst_structure_get_value(structure, "stream"); stream = g_value_get_object(value); - value = gst_structure_get_value(msg->structure, - "local-candidate"); + value = gst_structure_get_value(structure, "local-candidate"); local_candidate = g_value_get_boxed(value); - value = gst_structure_get_value(msg->structure, - "remote-candidate"); + value = gst_structure_get_value(structure, "remote-candidate"); remote_candidate = g_value_get_boxed(value); g_object_get(stream, "participant", &participant, NULL); @@ -1085,7 +1163,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, g_object_unref(lcandidate); g_object_unref(rcandidate); - } else if (gst_structure_has_name(msg->structure, + } else if (gst_structure_has_name(structure, #ifdef HAVE_FARSIGHT "farsight-recv-codecs-changed")) { #else @@ -1095,7 +1173,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, GList *codecs; FsCodec *codec; - value = gst_structure_get_value(msg->structure, "codecs"); + value = gst_structure_get_value(structure, "codecs"); codecs = g_value_get_boxed(value); codec = codecs->data; @@ -1106,7 +1184,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, "farstream-recv-codecs-changed: %s\n", #endif codec->encoding_name); - } else if (gst_structure_has_name(msg->structure, + } else if (gst_structure_has_name(structure, #ifdef HAVE_FARSIGHT "farsight-component-state-changed")) { #else @@ -1117,9 +1195,9 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, guint component; const gchar *state; - value = gst_structure_get_value(msg->structure, "state"); + value = gst_structure_get_value(structure, "state"); fsstate = g_value_get_enum(value); - value = gst_structure_get_value(msg->structure, "component"); + value = gst_structure_get_value(structure, "component"); component = g_value_get_uint(value); switch (fsstate) { @@ -1154,7 +1232,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, #endif "component: %u state: %s\n", component, state); - } else if (gst_structure_has_name(msg->structure, + } else if (gst_structure_has_name(structure, #ifdef HAVE_FARSIGHT "farsight-send-codec-changed")) { #else @@ -1164,7 +1242,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, FsCodec *codec; gchar *codec_str; - value = gst_structure_get_value(msg->structure, "codec"); + value = gst_structure_get_value(structure, "codec"); codec = g_value_get_boxed(value); codec_str = fs_codec_to_string(codec); @@ -1177,7 +1255,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, codec_str); g_free(codec_str); - } else if (gst_structure_has_name(msg->structure, + } else if (gst_structure_has_name(structure, #ifdef HAVE_FARSIGHT "farsight-codecs-changed")) { #else @@ -1187,7 +1265,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, FsSession *fssession; GList *sessions; - value = gst_structure_get_value(msg->structure, "session"); + value = gst_structure_get_value(structure, "session"); fssession = g_value_get_object(value); sessions = g_hash_table_get_values(priv->sessions); @@ -1631,7 +1709,11 @@ create_src(PurpleMediaBackendFs2 *self, const gchar *sess_id, srcpad = gst_element_get_static_pad(session->srcvalve, "src"); g_object_set(volume, "volume", input_volume, NULL); } else { +#if GST_CHECK_VERSION(1,0,0) + srcpad = gst_element_get_request_pad(session->tee, "src_%u"); +#else srcpad = gst_element_get_request_pad(session->tee, "src%d"); +#endif } purple_debug_info("backend-fs2", "connecting pad: %s\n", @@ -1641,11 +1723,14 @@ create_src(PurpleMediaBackendFs2 *self, const gchar *sess_id, gst_object_unref(session->src); gst_object_unref(sinkpad); - gst_element_set_state(session->src, GST_STATE_PLAYING); - purple_media_manager_create_output_window(purple_media_get_manager( priv->media), priv->media, sess_id, NULL); + purple_debug_info("backend-fs2", "create_src: setting source " + "state to GST_STATE_PLAYING - it may hang here on win32\n"); + gst_element_set_state(session->src, GST_STATE_PLAYING); + purple_debug_info("backend-fs2", "create_src: state set\n"); + return TRUE; } @@ -1849,14 +1934,10 @@ src_pad_added_cb(FsStream *fsstream, GstPad *srcpad, * audioresample ! audioconvert ! realsink */ stream->queue = gst_element_factory_make("queue", NULL); - stream->volume = gst_element_factory_make( - "volume", NULL); - g_object_set(stream->volume, "volume", - output_volume, NULL); - stream->level = gst_element_factory_make( - "level", NULL); - stream->src = gst_element_factory_make( - "liveadder", NULL); + stream->volume = gst_element_factory_make("volume", NULL); + g_object_set(stream->volume, "volume", output_volume, NULL); + stream->level = gst_element_factory_make("level", NULL); + stream->src = gst_element_factory_make("liveadder", NULL); sink = purple_media_manager_get_element( purple_media_get_manager(priv->media), PURPLE_MEDIA_RECV_AUDIO, priv->media, @@ -1875,10 +1956,12 @@ src_pad_added_cb(FsStream *fsstream, GstPad *srcpad, gst_element_link(stream->queue, stream->volume); sink = stream->queue; } else if (codec->media_type == FS_MEDIA_TYPE_VIDEO) { - stream->src = gst_element_factory_make( - "fsfunnel", NULL); - sink = gst_element_factory_make( - "fakesink", NULL); +#if GST_CHECK_VERSION(1,0,0) + stream->src = gst_element_factory_make("funnel", NULL); +#else + stream->src = gst_element_factory_make("fsfunnel", NULL); +#endif + sink = gst_element_factory_make("fakesink", NULL); g_object_set(G_OBJECT(sink), "async", FALSE, NULL); gst_bin_add(GST_BIN(priv->confbin), sink); gst_element_set_state(sink, GST_STATE_PLAYING); @@ -1892,7 +1975,11 @@ src_pad_added_cb(FsStream *fsstream, GstPad *srcpad, gst_element_link_many(stream->src, stream->tee, sink, NULL); } +#if GST_CHECK_VERSION(1,0,0) + sinkpad = gst_element_get_request_pad(stream->src, "sink_%u"); +#else sinkpad = gst_element_get_request_pad(stream->src, "sink%d"); +#endif gst_pad_link(srcpad, sinkpad); gst_object_unref(sinkpad); @@ -2074,8 +2161,8 @@ G_GNUC_END_IGNORE_DEPRECATIONS if (!fs_stream_set_transmitter(fsstream, transmitter, _params, _num_params, &err)) { purple_debug_error("backend-fs2", - "Could not set transmitter %s: %s.\n", - transmitter, err->message); + "Could not set transmitter %s: %s.\n", + transmitter, err ? err->message : NULL); g_clear_error(&err); g_free(_params); return FALSE; @@ -2394,38 +2481,6 @@ purple_media_backend_fs2_set_send_codec(PurpleMediaBackend *self, return TRUE; } -static void -purple_media_backend_fs2_set_params(PurpleMediaBackend *self, - guint num_params, GParameter *params) -{ - PurpleMediaBackendFs2Private *priv; - const gchar **supported = purple_media_backend_fs2_get_available_params(); - const gchar **p; - guint i; - - g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self)); - - priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); - - if (priv->conference == NULL && - !init_conference(PURPLE_MEDIA_BACKEND_FS2(self))) { - purple_debug_error("backend-fs2", - "Error initializing the conference.\n"); - return; - } - - for (i = 0; i != num_params; ++i) { - for (p = supported; *p != NULL; ++p) { - if (!strcmp(params[i].name, *p)) { - g_object_set(priv->conference, - params[i].name, g_value_get_string(¶ms[i].value), - NULL); - break; - } - } - } -} - static const gchar ** purple_media_backend_fs2_get_available_params(void) { @@ -2436,6 +2491,72 @@ purple_media_backend_fs2_get_available_params(void) return supported_params; } + +static const gchar* +param_to_sdes_type(const gchar *param) +{ + const gchar **supported = purple_media_backend_fs2_get_available_params(); + static const gchar *sdes_types[] = { + "cname", "email", "location", "name", "note", "phone", "tool", NULL + }; + guint i; + + for (i = 0; supported[i] != NULL; ++i) { + if (!strcmp(param, supported[i])) { + return sdes_types[i]; + } + } + + return NULL; +} + +static void +purple_media_backend_fs2_set_params(PurpleMediaBackend *self, + guint num_params, GParameter *params) +{ + PurpleMediaBackendFs2Private *priv; + guint i; +#ifndef HAVE_FARSIGHT + GstStructure *sdes; +#endif + + g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self)); + + priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); + + if (priv->conference == NULL && + !init_conference(PURPLE_MEDIA_BACKEND_FS2(self))) { + purple_debug_error("backend-fs2", + "Error initializing the conference.\n"); + return; + } + +#ifdef HAVE_FARSIGHT + for (i = 0; i != num_params; ++i) { + if (param_to_sdes_type(params[i].name)) { + g_object_set(priv->conference, + params[i].name, g_value_get_string(¶ms[i].value), + NULL); + } + } +#else + g_object_get(G_OBJECT(priv->conference), "sdes", &sdes, NULL); + + for (i = 0; i != num_params; ++i) { + const gchar *sdes_type = param_to_sdes_type(params[i].name); + if (!sdes_type) + continue; + + gst_structure_set(sdes, sdes_type, + G_TYPE_STRING, g_value_get_string(¶ms[i].value), + NULL); + } + + g_object_set(G_OBJECT(priv->conference), "sdes", sdes, NULL); + gst_structure_free(sdes); +#endif /* HAVE_FARSIGHT */ +} + #else GType purple_media_backend_fs2_get_type(void) @@ -2444,6 +2565,7 @@ purple_media_backend_fs2_get_type(void) } #endif /* USE_VV */ + #ifdef USE_GSTREAMER GstElement * purple_media_backend_fs2_get_src(PurpleMediaBackendFs2 *self, |