/pidgin/main: 4fe1034f3dce: Add application media type and APIs
Youness Alaoui <[email protected]>
| Newsgroups | gmane.comp.gnome.gaim.cvs |
|---|---|
| Message-ID | <[email protected]> |
Changeset: 4fe1034f3dce1c5cd3c929ab8c58db8e27655beb Author: Youness Alaoui <[email protected]> Date: 2014-07-21 17:53 -0400 Branch: release-2.x.y URL: https://hg.pidgin.im/pidgin/main/rev/4fe1034f3dce Description: Add application media type and APIs Fixes #16315 diffstat: configure.ac | 14 + libpurple/Makefile.am | 2 + libpurple/media-gst.h | 1 + libpurple/media/backend-fs2.c | 60 +++- libpurple/media/codec.c | 4 +- libpurple/media/enum-types.c | 6 + libpurple/media/enum-types.h | 6 +- libpurple/mediamanager.c | 673 +++++++++++++++++++++++++++++++++++++++++- libpurple/mediamanager.h | 89 +++++ 9 files changed, 849 insertions(+), 6 deletions(-) diffs (truncated from 1118 to 300 lines): diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -916,6 +916,20 @@ fi AM_CONDITIONAL(USE_VV, test "x$enable_vv" != "xno") dnl ####################################################################### +dnl # Check for Raw data streams support in Farstream +dnl ####################################################################### +if test "x$enable_vv" != "xno" -a "x$with_gstreamer" == "x1.0"; then + AC_MSG_CHECKING(for raw data support in Farstream) + PKG_CHECK_MODULES(GSTAPP, [gstreamer-app-1.0], [ + AC_DEFINE(USE_GSTAPP, 1, [Use GStreamer Video Overlay support]) + AC_SUBST(GSTAPP_CFLAGS) + AC_SUBST(GSTAPP_LIBS) + AC_DEFINE(HAVE_MEDIA_APPLICATION, 1, [Define if we have support for application media type.]) + AC_MSG_RESULT(yes) + ], [AC_MSG_RESULT(no)]) +fi + +dnl ####################################################################### dnl # Check for Internationalized Domain Name support dnl ####################################################################### diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am --- a/libpurple/Makefile.am +++ b/libpurple/Makefile.am @@ -309,6 +309,7 @@ libpurple_la_LIBADD = \ $(FARSTREAM_LIBS) \ $(GSTREAMER_LIBS) \ $(GSTVIDEO_LIBS) \ + $(GSTAPP_LIBS) \ $(GSTINTERFACES_LIBS) \ $(IDN_LIBS) \ ciphers/libpurple-ciphers.la \ @@ -326,6 +327,7 @@ AM_CPPFLAGS = \ $(FARSTREAM_CFLAGS) \ $(GSTREAMER_CFLAGS) \ $(GSTVIDEO_CFLAGS) \ + $(GSTAPP_CFLAGS) \ $(GSTINTERFACES_CFLAGS) \ $(IDN_CFLAGS) \ $(NETWORKMANAGER_CFLAGS) diff --git a/libpurple/media-gst.h b/libpurple/media-gst.h --- a/libpurple/media-gst.h +++ b/libpurple/media-gst.h @@ -71,6 +71,7 @@ typedef enum { PURPLE_MEDIA_ELEMENT_SRC = 1 << 9, /** can be set as an active src */ PURPLE_MEDIA_ELEMENT_SINK = 1 << 10, /** can be set as an active sink */ + PURPLE_MEDIA_ELEMENT_APPLICATION = 1 << 11, /** supports application data */ } PurpleMediaElementType; #ifdef __cplusplus diff --git a/libpurple/media/backend-fs2.c b/libpurple/media/backend-fs2.c --- a/libpurple/media/backend-fs2.c +++ b/libpurple/media/backend-fs2.c @@ -577,6 +577,10 @@ session_type_to_fs_media_type(PurpleMedi return FS_MEDIA_TYPE_AUDIO; else if (type & PURPLE_MEDIA_VIDEO) return FS_MEDIA_TYPE_VIDEO; +#ifdef HAVE_MEDIA_APPLICATION + else if (type & PURPLE_MEDIA_APPLICATION) + return FS_MEDIA_TYPE_APPLICATION; +#endif else return 0; } @@ -585,7 +589,7 @@ static FsStreamDirection session_type_to_fs_stream_direction(PurpleMediaSessionType type) { if ((type & PURPLE_MEDIA_AUDIO) == PURPLE_MEDIA_AUDIO || - (type & PURPLE_MEDIA_VIDEO) == PURPLE_MEDIA_VIDEO) + (type & PURPLE_MEDIA_VIDEO) == PURPLE_MEDIA_VIDEO) return FS_DIRECTION_BOTH; else if ((type & PURPLE_MEDIA_SEND_AUDIO) || (type & PURPLE_MEDIA_SEND_VIDEO)) @@ -593,6 +597,14 @@ session_type_to_fs_stream_direction(Purp else if ((type & PURPLE_MEDIA_RECV_AUDIO) || (type & PURPLE_MEDIA_RECV_VIDEO)) return FS_DIRECTION_RECV; +#ifdef HAVE_MEDIA_APPLICATION + else if ((type & PURPLE_MEDIA_APPLICATION) == PURPLE_MEDIA_APPLICATION) + return FS_DIRECTION_BOTH; + else if (type & PURPLE_MEDIA_SEND_APPLICATION) + return FS_DIRECTION_SEND; + else if (type & PURPLE_MEDIA_RECV_APPLICATION) + return FS_DIRECTION_RECV; +#endif else return FS_DIRECTION_NONE; } @@ -611,6 +623,13 @@ session_type_from_fs(FsMediaType type, F result |= PURPLE_MEDIA_SEND_VIDEO; if (direction & FS_DIRECTION_RECV) result |= PURPLE_MEDIA_RECV_VIDEO; +#ifdef HAVE_MEDIA_APPLICATION + } else if (type == FS_MEDIA_TYPE_APPLICATION) { + if (direction & FS_DIRECTION_SEND) + result |= PURPLE_MEDIA_SEND_APPLICATION; + if (direction & FS_DIRECTION_RECV) + result |= PURPLE_MEDIA_RECV_APPLICATION; +#endif } return result; } @@ -1367,7 +1386,8 @@ gst_handle_message_error(GstBus *bus, Gs & PURPLE_MEDIA_AUDIO) purple_media_error(priv->media, _("Error with your microphone")); - else + else if (purple_media_get_session_type(priv->media, + sessions->data) & PURPLE_MEDIA_VIDEO) purple_media_error(priv->media, _("Error with your webcam")); @@ -1790,6 +1810,21 @@ create_session(PurpleMediaBackendFs2 *se session->session = fs_conference_new_session(priv->conference, session_type_to_fs_media_type(type), &err); +#ifdef HAVE_MEDIA_APPLICATION + if (type == PURPLE_MEDIA_APPLICATION) { + GstCaps *caps; + GObject *rtpsession = NULL; + + caps = gst_caps_new_empty_simple ("application/octet-stream"); + fs_session_set_allowed_caps (session->session, caps, caps, NULL); + gst_caps_unref (caps); + g_object_get (session->session, "internal-session", &rtpsession, NULL); + if (rtpsession) { + g_object_set (rtpsession, "probation", 0, NULL); + g_object_unref (rtpsession); + } + } +#endif if (err != NULL) { purple_media_error(priv->media, _("Error creating session: %s"), @@ -2004,6 +2039,21 @@ src_pad_added_cb(FsStream *fsstream, Gst gst_bin_add(GST_BIN(priv->confbin), sink); gst_element_set_state(sink, GST_STATE_PLAYING); stream->fakesink = sink; +#ifdef HAVE_MEDIA_APPLICATION + } else if (codec->media_type == FS_MEDIA_TYPE_APPLICATION) { +#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 = purple_media_manager_get_element( + purple_media_get_manager(priv->media), + PURPLE_MEDIA_RECV_APPLICATION, priv->media, + stream->session->id, + stream->participant); + gst_bin_add(GST_BIN(priv->confbin), sink); + gst_element_set_state(sink, GST_STATE_PLAYING); +#endif } stream->tee = gst_element_factory_make("tee", NULL); gst_bin_add_many(GST_BIN(priv->confbin), @@ -2366,6 +2416,9 @@ purple_media_backend_fs2_codecs_ready(Pu return FALSE; if (session->type & (PURPLE_MEDIA_SEND_AUDIO | +#ifdef HAVE_MEDIA_APPLICATION + PURPLE_MEDIA_SEND_APPLICATION | +#endif PURPLE_MEDIA_SEND_VIDEO)) { #ifdef HAVE_FARSIGHT g_object_get(session->session, @@ -2389,6 +2442,9 @@ purple_media_backend_fs2_codecs_ready(Pu PurpleMediaBackendFs2Session *session = values->data; if (session->type & (PURPLE_MEDIA_SEND_AUDIO | +#ifdef HAVE_MEDIA_APPLICATION + PURPLE_MEDIA_SEND_APPLICATION | +#endif PURPLE_MEDIA_SEND_VIDEO)) { #ifdef HAVE_FARSIGHT g_object_get(session->session, diff --git a/libpurple/media/codec.c b/libpurple/media/codec.c --- a/libpurple/media/codec.c +++ b/libpurple/media/codec.c @@ -188,7 +188,7 @@ purple_media_codec_class_init(PurpleMedi g_object_class_install_property(gobject_class, PROP_MEDIA_TYPE, g_param_spec_flags("media-type", "Media Type", - "Whether this is an audio of video codec.", + "Whether this is an audio, video or application codec.", PURPLE_TYPE_MEDIA_SESSION_TYPE, PURPLE_MEDIA_NONE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); @@ -402,6 +402,8 @@ purple_media_codec_to_string(const Purpl media_type_str = "audio"; else if (priv->media_type & PURPLE_MEDIA_VIDEO) media_type_str = "video"; + else if (priv->media_type & PURPLE_MEDIA_APPLICATION) + media_type_str = "application"; g_string_printf(string, "%d: %s %s clock:%d channels:%d", priv->id, media_type_str, priv->encoding_name, diff --git a/libpurple/media/enum-types.c b/libpurple/media/enum-types.c --- a/libpurple/media/enum-types.c +++ b/libpurple/media/enum-types.c @@ -182,10 +182,16 @@ purple_media_session_type_get_type() "PURPLE_MEDIA_RECV_VIDEO", "recv-video" }, { PURPLE_MEDIA_SEND_VIDEO, "PURPLE_MEDIA_SEND_VIDEO", "send-video" }, + { PURPLE_MEDIA_RECV_APPLICATION, + "PURPLE_MEDIA_RECV_APPLICATION", "recv-application" }, + { PURPLE_MEDIA_SEND_APPLICATION, + "PURPLE_MEDIA_SEND_APPLICATION", "send-application" }, { PURPLE_MEDIA_AUDIO, "PURPLE_MEDIA_AUDIO", "audio" }, { PURPLE_MEDIA_VIDEO, "PURPLE_MEDIA_VIDEO", "video" }, + { PURPLE_MEDIA_APPLICATION, + "PURPLE_MEDIA_APPLICATION", "application" }, { 0, NULL, NULL } }; type = g_flags_register_static( diff --git a/libpurple/media/enum-types.h b/libpurple/media/enum-types.h --- a/libpurple/media/enum-types.h +++ b/libpurple/media/enum-types.h @@ -94,8 +94,12 @@ typedef enum { PURPLE_MEDIA_SEND_AUDIO = 1 << 1, PURPLE_MEDIA_RECV_VIDEO = 1 << 2, PURPLE_MEDIA_SEND_VIDEO = 1 << 3, + PURPLE_MEDIA_RECV_APPLICATION = 1 << 4, + PURPLE_MEDIA_SEND_APPLICATION = 1 << 5, PURPLE_MEDIA_AUDIO = PURPLE_MEDIA_RECV_AUDIO | PURPLE_MEDIA_SEND_AUDIO, - PURPLE_MEDIA_VIDEO = PURPLE_MEDIA_RECV_VIDEO | PURPLE_MEDIA_SEND_VIDEO + PURPLE_MEDIA_VIDEO = PURPLE_MEDIA_RECV_VIDEO | PURPLE_MEDIA_SEND_VIDEO, + PURPLE_MEDIA_APPLICATION = PURPLE_MEDIA_RECV_APPLICATION | + PURPLE_MEDIA_SEND_APPLICATION } PurpleMediaSessionType; /** Media state-changed types */ diff --git a/libpurple/mediamanager.c b/libpurple/mediamanager.c --- a/libpurple/mediamanager.c +++ b/libpurple/mediamanager.c @@ -44,6 +44,9 @@ #else #include <farstream/fs-element-added-notifier.h> #endif +#ifdef HAVE_MEDIA_APPLICATION +#include <gst/app/app.h> +#endif #if GST_CHECK_VERSION(1,0,0) #include <gst/video/videooverlay.h> @@ -97,14 +100,45 @@ struct _PurpleMediaManagerPrivate PurpleMediaElementInfo *video_sink; PurpleMediaElementInfo *audio_src; PurpleMediaElementInfo *audio_sink; + +#ifdef HAVE_MEDIA_APPLICATION + /* Application data streams */ + GList *appdata_info; /* holds PurpleMediaAppDataInfo */ + GMutex appdata_mutex; +#endif }; +#ifdef HAVE_MEDIA_APPLICATION +typedef struct { + PurpleMedia *media; + GWeakRef media_ref; + gchar *session_id; + gchar *participant; + PurpleMediaAppDataCallbacks callbacks; + gpointer user_data; + GDestroyNotify notify; + GstAppSrc *appsrc; + GstAppSink *appsink; + gint num_samples; + GstSample *current_sample; + guint sample_offset; + gboolean writable; + gboolean connected; + guint writable_timer_id; + guint readable_timer_id; + GCond readable_cond; +} PurpleMediaAppDataInfo; +#endif + #define PURPLE_MEDIA_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManagerPrivate)) #define PURPLE_MEDIA_ELEMENT_INFO_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA_ELEMENT_INFO, PurpleMediaElementInfoPrivate)) static void purple_media_manager_class_init (PurpleMediaManagerClass *klass); static void purple_media_manager_init (PurpleMediaManager *media); static void purple_media_manager_finalize (GObject *object); +#ifdef HAVE_MEDIA_APPLICATION +static void free_appdata_info_locked (PurpleMediaAppDataInfo *info); +#endif static GObjectClass *parent_class = NULL; @@ -190,8 +224,10 @@ purple_media_manager_init (PurpleMediaMa media->priv->medias = NULL; media->priv->private_medias = NULL;