soc.2008.vv: fc6e10ef: Updates voice and video to use Farsight ...
maiku at soc.pidgin.im
maiku at soc.pidgin.im
Thu May 22 23:40:41 EDT 2008
-----------------------------------------------------------------
Revision: fc6e10ef43f0dfaf9065bebff76a0e090460990f
Ancestor: 7872d32a910cd4c1fbc3e2457295e4c1d40188f5
Author: maiku at soc.pidgin.im
Date: 2008-05-23T02:42:32
Branch: im.pidgin.soc.2008.vv
URL: http://d.pidgin.im/viewmtn/revision/info/fc6e10ef43f0dfaf9065bebff76a0e090460990f
Added files:
libpurple/marshallers.list
Modified files:
configure.ac finch/gntmedia.c finch/gntmedia.h
libpurple/Makefile.am libpurple/media.c libpurple/media.h
libpurple/mediamanager.c libpurple/mediamanager.h
libpurple/protocols/jabber/google.c
libpurple/protocols/jabber/jabber.c
libpurple/protocols/jabber/jingle.c
libpurple/protocols/jabber/jingle.h pidgin/gtkmedia.c
pidgin/gtkmedia.h
ChangeLog:
Updates voice and video to use Farsight 2, gets XMPP voice conferences
closer to XEP-0167, and fixes a lot of bugs.
-------------- next part --------------
============================================================
--- libpurple/marshallers.list 1a7907ac8dc61b478097e360c2c2f57240d4f483
+++ libpurple/marshallers.list 1a7907ac8dc61b478097e360c2c2f57240d4f483
@@ -0,0 +1 @@
+VOID:BOXED,BOXED
============================================================
--- configure.ac 3b768d9ce317f8fd2477edbb19b6d42ecae1bdae
+++ configure.ac d106aed8151b1329fe6bac22603e85be78350306
@@ -318,6 +318,9 @@ AC_SUBST(GLIB_LIBS)
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
+GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0`
+AC_SUBST(GLIB_GENMARSHAL)
+
AC_ARG_WITH([extraversion],
AC_HELP_STRING([--with-extraversion=STRING],
[extra version number to be displayed in Help->About and --help (for packagers)]),
@@ -721,11 +724,11 @@ dnl ####################################
dnl #######################################################################
dnl # Check for Farsight
dnl #######################################################################
-AC_ARG_ENABLE(farsight,
+AC_ARG_ENABLE(farsight2,
[AC_HELP_STRING([--disable-vv], [compile without voice and video support])],
enable_farsight="$enableval", enable_farsight="yes")
if test "x$enable_farsight" != "xno"; then
- PKG_CHECK_MODULES(FARSIGHT, [farsight-0.1], [
+ PKG_CHECK_MODULES(FARSIGHT, [farsight2-0.10], [
AC_DEFINE(USE_FARSIGHT, 1, [Use Farsight for voice and video])
AC_SUBST(FARSIGHT_CFLAGS)
AC_SUBST(FARSIGHT_LIBS)
============================================================
--- finch/gntmedia.c 66bf4e18cac9a0eff3414498eeee5a70638de436
+++ finch/gntmedia.c 4f92f2e4c444cf07f213de86c099d524c1aafdd2
@@ -42,8 +42,6 @@
/* An incredibly large part of the following is from gtkmedia.c */
#ifdef USE_FARSIGHT
-#include <farsight/farsight.h>
-
#undef hangup
struct _FinchMediaPrivate
============================================================
--- finch/gntmedia.h 107f86a0bc0ca7a3042a56f917f969e6a7556bc5
+++ finch/gntmedia.h 70481c874d95d4f3dd1d97b1f75ab15c0bc9878d
@@ -33,7 +33,6 @@
#ifdef USE_FARSIGHT
-#include <farsight/farsight.h>
#include <glib-object.h>
#include "gntbox.h"
============================================================
--- libpurple/Makefile.am dc287c22222942e1a6d45a187a32e870856477a6
+++ libpurple/Makefile.am c3476ea3ecce49e60fa7e9922f8aa0c6593430df
@@ -1,6 +1,7 @@ EXTRA_DIST = \
EXTRA_DIST = \
dbus-analyze-functions.py \
dbus-analyze-types.py \
+ marshallers.list \
purple-notifications-example \
purple-remote \
purple-send \
@@ -51,6 +52,7 @@ purple_coresources = \
idle.c \
imgstore.c \
log.c \
+ marshallers.c \
media.c \
mediamanager.c \
mime.c \
@@ -105,6 +107,7 @@ purple_coreheaders = \
idle.h \
imgstore.h \
log.h \
+ marshallers.h \
media.h \
mediamanager.h \
mime.h \
@@ -139,6 +142,14 @@ purple_builtheaders = purple.h version.h
purple_builtheaders = purple.h version.h
+marshallers.h: marshallers.list
+ @echo "Generating marshallers.h"
+ $(GLIB_GENMARSHAL) --prefix=purple_smarshal $(srcdir)/marshallers.list --header > marshallers.h
+
+marshallers.c: marshallers.list
+ @echo "Generating marshallers.c"
+ $(GLIB_GENMARSHAL) --prefix=purple_smarshal $(srcdir)/marshallers.list --body > marshallers.c
+
if ENABLE_DBUS
CLEANFILES = \
@@ -147,6 +158,8 @@ CLEANFILES = \
dbus-client-binding.h \
dbus-types.c \
dbus-types.h \
+ marshallers.c \
+ marshallers.h \
purple-client-bindings.c \
purple-client-bindings.h \
purple.service
@@ -217,6 +230,8 @@ BUILT_SOURCES = $(purple_builtheaders) \
dbus-types.c \
dbus-types.h \
dbus-bindings.c \
+ marshallers.c \
+ marshallers.h \
purple-client-bindings.c \
purple-client-bindings.h
============================================================
--- libpurple/media.c 9119e05f4aca04bf2fc7105bdb03d856033c80cc
+++ libpurple/media.c a10fd2a1af54fc09b4ad740735a1d21ecbf918c2
@@ -29,6 +29,7 @@
#include "connection.h"
#include "media.h"
+#include "marshallers.h"
#include "debug.h"
@@ -36,11 +37,11 @@
#ifdef USE_GSTPROPS
#include <gst/interfaces/propertyprobe.h>
-#include <farsight/farsight.h>
+#include <gst/farsight/fs-conference-iface.h>
struct _PurpleMediaPrivate
{
- FarsightSession *farsight_session;
+ FsConference *conference;
char *name;
PurpleConnection *connection;
@@ -49,8 +50,23 @@ struct _PurpleMediaPrivate
GstElement *video_src;
GstElement *video_sink;
- FarsightStream *audio_stream;
- FarsightStream *video_stream;
+ FsSession *audio_session;
+ FsSession *video_session;
+
+ GList *participants; /* FsParticipant list */
+ GList *audio_streams; /* FsStream list */
+ GList *video_streams; /* FsStream list */
+
+ /* might be able to just combine these two */
+ GstElement *audio_pipeline;
+ GstElement *video_pipeline;
+
+ /* this will need to be stored/handled per stream
+ * once having multiple streams is supported */
+ GList *local_candidates;
+
+ FsCandidate *local_candidate;
+ FsCandidate *remote_candidate;
};
#define PURPLE_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA, PurpleMediaPrivate))
@@ -73,21 +89,23 @@ enum {
REJECT,
GOT_HANGUP,
GOT_ACCEPT,
+ CANDIDATES_PREPARED,
+ CANDIDATE_PAIR,
LAST_SIGNAL
};
static guint purple_media_signals[LAST_SIGNAL] = {0};
enum {
PROP_0,
- PROP_FARSIGHT_SESSION,
+ PROP_FS_CONFERENCE,
PROP_NAME,
PROP_CONNECTION,
PROP_AUDIO_SRC,
PROP_AUDIO_SINK,
PROP_VIDEO_SRC,
PROP_VIDEO_SINK,
- PROP_VIDEO_STREAM,
- PROP_AUDIO_STREAM
+ PROP_VIDEO_SESSION,
+ PROP_AUDIO_SESSION
};
GType
@@ -113,7 +131,6 @@ purple_media_get_type()
return type;
}
-
static void
purple_media_class_init (PurpleMediaClass *klass)
{
@@ -124,11 +141,11 @@ purple_media_class_init (PurpleMediaClas
gobject_class->set_property = purple_media_set_property;
gobject_class->get_property = purple_media_get_property;
- g_object_class_install_property(gobject_class, PROP_FARSIGHT_SESSION,
- g_param_spec_object("farsight-session",
- "Farsight session",
- "The FarsightSession associated with this media.",
- FARSIGHT_TYPE_SESSION,
+ g_object_class_install_property(gobject_class, PROP_FS_CONFERENCE,
+ g_param_spec_object("farsight-conference",
+ "Farsight conference",
+ "The FsConference associated with this media.",
+ FS_TYPE_CONFERENCE,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
g_object_class_install_property(gobject_class, PROP_NAME,
@@ -172,18 +189,18 @@ purple_media_class_init (PurpleMediaClas
GST_TYPE_ELEMENT,
G_PARAM_READWRITE));
- g_object_class_install_property(gobject_class, PROP_VIDEO_STREAM,
- g_param_spec_object("video-stream",
+ g_object_class_install_property(gobject_class, PROP_VIDEO_SESSION,
+ g_param_spec_object("video-session",
"Video stream",
"The FarsightStream used for video",
- FARSIGHT_TYPE_STREAM,
+ FS_TYPE_SESSION,
G_PARAM_READWRITE));
- g_object_class_install_property(gobject_class, PROP_AUDIO_STREAM,
- g_param_spec_object("audio-stream",
+ g_object_class_install_property(gobject_class, PROP_AUDIO_SESSION,
+ g_param_spec_object("audio-session",
"Audio stream",
"The FarsightStream used for audio",
- FARSIGHT_TYPE_STREAM,
+ FS_TYPE_SESSION,
G_PARAM_READWRITE));
purple_media_signals[READY] = g_signal_new("ready", G_TYPE_FROM_CLASS(klass),
@@ -214,6 +231,14 @@ purple_media_class_init (PurpleMediaClas
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ purple_media_signals[CANDIDATES_PREPARED] = g_signal_new("candidates-prepared", G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ purple_media_signals[CANDIDATE_PAIR] = g_signal_new("candidate-pair", G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ purple_smarshal_VOID__BOXED_BOXED,
+ G_TYPE_NONE, 2, FS_TYPE_CANDIDATE, FS_TYPE_CANDIDATE);
g_type_class_add_private(klass, sizeof(PurpleMediaPrivate));
}
@@ -241,11 +266,11 @@ purple_media_set_property (GObject *obje
media = PURPLE_MEDIA(object);
switch (prop_id) {
- case PROP_FARSIGHT_SESSION:
- if (media->priv->farsight_session)
- g_object_unref(media->priv->farsight_session);
- media->priv->farsight_session = g_value_get_object(value);
- g_object_ref(media->priv->farsight_session);
+ case PROP_FS_CONFERENCE:
+ if (media->priv->conference)
+ g_object_unref(media->priv->conference);
+ media->priv->conference = g_value_get_object(value);
+ g_object_ref(media->priv->conference);
break;
case PROP_NAME:
g_free(media->priv->name);
@@ -259,12 +284,16 @@ purple_media_set_property (GObject *obje
gst_object_unref(media->priv->audio_src);
media->priv->audio_src = g_value_get_object(value);
gst_object_ref(media->priv->audio_src);
+ gst_bin_add(GST_BIN(purple_media_get_audio_pipeline(media)),
+ media->priv->audio_src);
break;
case PROP_AUDIO_SINK:
if (media->priv->audio_sink)
gst_object_unref(media->priv->audio_sink);
media->priv->audio_sink = g_value_get_object(value);
gst_object_ref(media->priv->audio_sink);
+ gst_bin_add(GST_BIN(purple_media_get_audio_pipeline(media)),
+ media->priv->audio_sink);
break;
case PROP_VIDEO_SRC:
if (media->priv->video_src)
@@ -278,17 +307,17 @@ purple_media_set_property (GObject *obje
media->priv->video_sink = g_value_get_object(value);
gst_object_ref(media->priv->video_sink);
break;
- case PROP_VIDEO_STREAM:
- if (media->priv->video_stream)
- g_object_unref(media->priv->video_stream);
- media->priv->video_stream = g_value_get_object(value);
- gst_object_ref(media->priv->video_stream);
+ case PROP_VIDEO_SESSION:
+ if (media->priv->video_session)
+ g_object_unref(media->priv->video_session);
+ media->priv->video_session = g_value_get_object(value);
+ gst_object_ref(media->priv->video_session);
break;
- case PROP_AUDIO_STREAM:
- if (media->priv->audio_stream)
- g_object_unref(media->priv->audio_stream);
- media->priv->audio_stream = g_value_get_object(value);
- gst_object_ref(media->priv->audio_stream);
+ case PROP_AUDIO_SESSION:
+ if (media->priv->audio_session)
+ g_object_unref(media->priv->audio_session);
+ media->priv->audio_session = g_value_get_object(value);
+ gst_object_ref(media->priv->audio_session);
break;
default:
@@ -306,8 +335,8 @@ purple_media_get_property (GObject *obje
media = PURPLE_MEDIA(object);
switch (prop_id) {
- case PROP_FARSIGHT_SESSION:
- g_value_set_object(value, media->priv->farsight_session);
+ case PROP_FS_CONFERENCE:
+ g_value_set_object(value, media->priv->conference);
break;
case PROP_NAME:
g_value_set_string(value, media->priv->name);
@@ -327,11 +356,11 @@ purple_media_get_property (GObject *obje
case PROP_VIDEO_SINK:
g_value_set_object(value, media->priv->video_sink);
break;
- case PROP_VIDEO_STREAM:
- g_value_set_object(value, media->priv->video_stream);
+ case PROP_VIDEO_SESSION:
+ g_value_set_object(value, media->priv->video_session);
break;
- case PROP_AUDIO_STREAM:
- g_value_set_object(value, media->priv->audio_stream);
+ case PROP_AUDIO_SESSION:
+ g_value_set_object(value, media->priv->audio_session);
break;
default:
@@ -415,12 +444,12 @@ purple_media_get_audio_pipeline(PurpleMe
GstElement *
purple_media_get_audio_pipeline(PurpleMedia *media)
{
- FarsightStream *stream;
- g_object_get(G_OBJECT(media), "audio-stream", &stream, NULL);
-printf("stream: %d\n\n\n", stream);
-GstElement *l = farsight_stream_get_pipeline(stream);
-printf("Element: %d\n", l);
- return farsight_stream_get_pipeline(stream);
+ if (!media->priv->audio_pipeline) {
+ media->priv->audio_pipeline = gst_pipeline_new(media->priv->name);
+ gst_bin_add(GST_BIN(media->priv->audio_pipeline), GST_ELEMENT(media->priv->conference));
+ }
+
+ return media->priv->audio_pipeline;
}
PurpleConnection *
@@ -631,5 +660,237 @@ purple_media_audio_init_recv(GstElement
purple_debug_info("media", "purple_media_audio_init_recv end\n");
}
+static void
+purple_media_new_local_candidate(FsStream *stream,
+ FsCandidate *local_candidate,
+ PurpleMedia *media)
+{
+ purple_debug_info("media", "got new local candidate: %s\n", local_candidate->candidate_id);
+ media->priv->local_candidates = g_list_append(media->priv->local_candidates,
+ fs_candidate_copy(local_candidate));
+}
+
+static void
+purple_media_candidates_prepared(FsStream *stream, PurpleMedia *media)
+{
+ g_signal_emit(media, purple_media_signals[CANDIDATES_PREPARED], 0);
+}
+
+/* callback called when a pair of transport candidates (local and remote)
+ * has been established */
+static void
+purple_media_candidate_pair_established(FsStream *stream,
+ FsCandidate *native_candidate,
+ FsCandidate *remote_candidate,
+ PurpleMedia *media)
+{
+ media->priv->local_candidate = fs_candidate_copy(native_candidate);
+ media->priv->remote_candidate = fs_candidate_copy(remote_candidate);
+
+ purple_debug_info("media", "candidate pair established\n");
+ g_signal_emit(media, purple_media_signals[CANDIDATE_PAIR], 0,
+ media->priv->local_candidate,
+ media->priv->remote_candidate);
+}
+
+static void
+purple_media_src_pad_added(FsStream *stream, GstPad *srcpad,
+ FsCodec *codec, PurpleMedia *media)
+{
+ GstElement *pipeline = purple_media_get_audio_pipeline(media);
+ GstPad *sinkpad = gst_element_get_static_pad(purple_media_get_audio_sink(media), "ghostsink");
+ purple_debug_info("media", "connecting new src pad: %s\n",
+ gst_pad_link(srcpad, sinkpad) == GST_PAD_LINK_OK ? "success" : "failure");
+ gst_element_set_state(pipeline, GST_STATE_PLAYING);
+}
+
+static void
+purple_media_add_stream_internal(PurpleMedia *media, FsSession **session, GList **streams,
+ GstElement *src, const gchar *who, FsMediaType type,
+ FsStreamDirection type_direction, const gchar *transmitter)
+{
+ char *cname = NULL;
+ FsParticipant *participant = NULL;
+ GList *l = NULL;
+ FsStream *stream = NULL;
+ FsParticipant *p = NULL;
+ FsStreamDirection *direction = NULL;
+ FsSession *s = NULL;
+
+ if (!*session) {
+ *session = fs_conference_new_session(media->priv->conference, type, NULL);
+ if (src) {
+ GstPad *sinkpad;
+ GstPad *srcpad;
+ g_object_get(*session, "sink-pad", &sinkpad, NULL);
+ srcpad = gst_element_get_static_pad(src, "ghostsrc");
+ purple_debug_info("media", "connecting pad: %s\n",
+ gst_pad_link(srcpad, sinkpad) == GST_PAD_LINK_OK
+ ? "success" : "failure");
+ }
+ }
+
+ for (l = media->priv->participants; l != NULL; l = g_list_next(l)) {
+ g_object_get(l->data, "cname", cname, NULL);
+ if (!strcmp(cname, who)) {
+ g_free(cname);
+ participant = l->data;
+ break;
+ }
+ g_free(cname);
+ }
+
+ if (!participant) {
+ participant = fs_conference_new_participant(media->priv->conference, (gchar*)who, NULL);
+ media->priv->participants = g_list_prepend(media->priv->participants, participant);
+ }
+
+ for (l = *streams; l != NULL; l = g_list_next(l)) {
+ g_object_get(l->data, "participant", &p, "direction", &direction, "session", &s, NULL);
+
+ if (participant == p && *session == s) {
+ stream = l->data;
+ break;
+ }
+ }
+
+ if (!stream) {
+ stream = fs_session_new_stream(*session, participant,
+ type_direction, transmitter, 0, NULL, NULL);
+ *streams = g_list_prepend(*streams, stream);
+ /* callback for new local candidate (new local candidate retreived) */
+ g_signal_connect(G_OBJECT(stream),
+ "new-local-candidate", G_CALLBACK(purple_media_new_local_candidate), media);
+ /* callback for source pad added (new stream source ready) */
+ g_signal_connect(G_OBJECT(stream),
+ "src-pad-added", G_CALLBACK(purple_media_src_pad_added), media);
+ /* callback for local candidates prepared (local candidates ready to send) */
+ g_signal_connect(G_OBJECT(stream),
+ "local-candidates-prepared",
+ G_CALLBACK(purple_media_candidates_prepared), media);
+ /* callback for new active candidate pair (established connection) */
+ g_signal_connect(G_OBJECT(stream),
+ "new-active-candidate-pair",
+ G_CALLBACK(purple_media_candidate_pair_established), media);
+ } else if (*direction != type_direction) {
+ /* change direction */
+ g_object_set(stream, "direction", type_direction, NULL);
+ }
+}
+
+void
+purple_media_add_stream(PurpleMedia *media, const gchar *who,
+ PurpleMediaStreamType type,
+ const gchar *transmitter)
+{
+ FsStreamDirection type_direction;
+
+ if (type & PURPLE_MEDIA_AUDIO) {
+ if (type & PURPLE_MEDIA_SEND_AUDIO && type & PURPLE_MEDIA_RECV_AUDIO)
+ type_direction = FS_DIRECTION_BOTH;
+ else if (type & PURPLE_MEDIA_SEND_AUDIO)
+ type_direction = FS_DIRECTION_SEND;
+ else if (type & PURPLE_MEDIA_RECV_AUDIO)
+ type_direction = FS_DIRECTION_RECV;
+ else
+ type_direction = FS_DIRECTION_NONE;
+
+ purple_media_add_stream_internal(media, &media->priv->audio_session,
+ &media->priv->audio_streams,
+ media->priv->audio_src, who,
+ FS_MEDIA_TYPE_AUDIO, type_direction,
+ transmitter);
+ }
+ if (type & PURPLE_MEDIA_VIDEO) {
+ if (type & PURPLE_MEDIA_SEND_VIDEO && type & PURPLE_MEDIA_RECV_VIDEO)
+ type_direction = FS_DIRECTION_BOTH;
+ else if (type & PURPLE_MEDIA_SEND_VIDEO)
+ type_direction = FS_DIRECTION_SEND;
+ else if (type & PURPLE_MEDIA_RECV_VIDEO)
+ type_direction = FS_DIRECTION_RECV;
+ else
+ type_direction = FS_DIRECTION_NONE;
+
+ purple_media_add_stream_internal(media, &media->priv->video_session,
+ &media->priv->video_streams,
+ media->priv->video_src, who,
+ FS_MEDIA_TYPE_VIDEO, type_direction,
+ transmitter);
+ }
+}
+
+void
+purple_media_remove_stream(PurpleMedia *media, const gchar *who, PurpleMediaStreamType type)
+{
+
+}
+
+static FsStream *
+purple_media_get_audio_stream(PurpleMedia *media, const gchar *name)
+{
+ GList *streams = media->priv->audio_streams;
+ for (; streams; streams = streams->next) {
+ FsParticipant *participant;
+ gchar *cname;
+ g_object_get(streams->data, "participant", &participant, NULL);
+ g_object_get(participant, "cname", &cname, NULL);
+
+ if (!strcmp(cname, name)) {
+ return streams->data;
+ }
+ }
+
+ return NULL;
+}
+
+GList *
+purple_media_get_local_audio_codecs(PurpleMedia *media)
+{
+ GList *codecs;
+ g_object_get(G_OBJECT(media->priv->audio_session), "local-codecs", &codecs, NULL);
+ return codecs;
+}
+
+GList *
+purple_media_get_local_audio_candidates(PurpleMedia *media)
+{
+ return media->priv->local_candidates;
+}
+
+GList *
+purple_media_get_negotiated_audio_codecs(PurpleMedia *media)
+{
+ GList *codec_intersection;
+ g_object_get(media->priv->audio_session, "negotiated-codecs", &codec_intersection, NULL);
+ return codec_intersection;
+}
+
+void
+purple_media_add_remote_audio_candidates(PurpleMedia *media, const gchar *name, GList *remote_candidates)
+{
+ FsStream *stream = purple_media_get_audio_stream(media, name);
+ GList *candidates = remote_candidates;
+ for (; candidates; candidates = candidates->next)
+ fs_stream_add_remote_candidate(stream, candidates->data, NULL);
+}
+
+FsCandidate *
+purple_media_get_local_candidate(PurpleMedia *media)
+{
+ return media->priv->local_candidate;
+}
+
+FsCandidate *
+purple_media_get_remote_candidate(PurpleMedia *media)
+{
+ return media->priv->remote_candidate;
+}
+
+void
+purple_media_set_remote_audio_codecs(PurpleMedia *media, const gchar *name, GList *codecs)
+{
+ fs_stream_set_remote_codecs(purple_media_get_audio_stream(media, name), codecs, NULL);
+}
+
#endif /* USE_GSTPROPS */
#endif /* USE_FARSIGHT */
============================================================
--- libpurple/media.h 13db098c626e2dd8b7183d9b9a10dc7ea012f088
+++ libpurple/media.h 1e2287929882130f00243b1cd5de5a01281970bc
@@ -29,7 +29,9 @@
#ifdef USE_FARSIGHT
#ifdef USE_GSTPROPS
-#include <farsight/farsight.h>
+#include <gst/gst.h>
+#include <gst/farsight/fs-stream.h>
+#include <gst/farsight/fs-session.h>
#include <glib.h>
#include <glib-object.h>
@@ -53,6 +55,8 @@ typedef enum {
PURPLE_MEDIA_SEND_AUDIO = 1 << 1,
PURPLE_MEDIA_RECV_VIDEO = 1 << 2,
PURPLE_MEDIA_SEND_VIDEO = 1 << 3,
+ PURPLE_MEDIA_AUDIO = PURPLE_MEDIA_RECV_AUDIO | PURPLE_MEDIA_SEND_AUDIO,
+ PURPLE_MEDIA_VIDEO = PURPLE_MEDIA_RECV_VIDEO | PURPLE_MEDIA_SEND_VIDEO
} PurpleMediaStreamType;
struct _PurpleMediaClass
@@ -109,6 +113,20 @@ void purple_media_audio_init_recv(GstEle
void purple_media_audio_init_recv(GstElement **recvbin, GstElement **recvlevel);
+void purple_media_add_stream(PurpleMedia *media, const gchar *who,
+ PurpleMediaStreamType type, const gchar *transmitter);
+void purple_media_remove_stream(PurpleMedia *media, const gchar *who, PurpleMediaStreamType type);
+
+GList *purple_media_get_local_audio_candidates(PurpleMedia *media);
+GList *purple_media_get_negotiated_audio_codecs(PurpleMedia *media);
+
+GList *purple_media_get_local_audio_codecs(PurpleMedia *media);
+void purple_media_add_remote_audio_candidates(PurpleMedia *media, const gchar *name,
+ GList *remote_candidates);
+FsCandidate *purple_media_get_local_candidate(PurpleMedia *media);
+FsCandidate *purple_media_get_remote_candidate(PurpleMedia *media);
+void purple_media_set_remote_audio_codecs(PurpleMedia *media, const gchar *name, GList *codecs);
+
G_END_DECLS
#endif /* USE_GSTPROPS */
============================================================
--- libpurple/mediamanager.c 6146c63c8c207044707830d2e7471f3833b4a0d8
+++ libpurple/mediamanager.c c811c384fa5425282ccb9594681ccd765a8bfd14
@@ -31,7 +31,7 @@
#ifdef USE_FARSIGHT
-#include <farsight/farsight.h>
+#include <gst/farsight/fs-conference-iface.h>
struct _PurpleMediaManagerPrivate
{
@@ -127,18 +127,19 @@ purple_media_manager_get()
return manager;
}
-PurpleMedia*
-purple_media_manager_create_media(PurpleMediaManager *manager,
+PurpleMedia *
+purple_media_manager_create_media(PurpleMediaManager *manager,
PurpleConnection *gc,
- const char *screenname,
- FarsightStream *audio_stream,
- FarsightStream *video_stream)
+ const char *conference_type,
+ const char *remote_user)
{
+ FsConference *conference = FS_CONFERENCE(gst_element_factory_make(conference_type, NULL));
+
PurpleMedia *media = PURPLE_MEDIA(g_object_new(purple_media_get_type(),
- "screenname", screenname,
+ "screenname", remote_user,
"connection", gc,
- "audio-stream", audio_stream,
- "video-stream", video_stream, NULL));
+ "farsight-conference", conference,
+ NULL));
manager->priv->medias = g_list_append(manager->priv->medias, media);
g_signal_emit(manager, purple_media_manager_signals[INIT_MEDIA], 0, media);
return media;
============================================================
--- libpurple/mediamanager.h d2abc484564d64e1514ed4d08537d09c6f4f112b
+++ libpurple/mediamanager.h d63d0a75c4ff9a695b3ec02224494597f4633fe2
@@ -28,7 +28,7 @@
#ifdef USE_FARSIGHT
-#include <farsight/farsight.h>
+#include <gst/farsight/fs-session.h>
#include <glib.h>
#include <glib-object.h>
@@ -61,12 +61,10 @@ PurpleMediaManager *purple_media_manager
GType purple_media_manager_get_type(void);
PurpleMediaManager *purple_media_manager_get(void);
-
PurpleMedia *purple_media_manager_create_media(PurpleMediaManager *manager,
- PurpleConnection *gc,
- const char *screenname,
- FarsightStream *audio_stream,
- FarsightStream *video_stream);
+ PurpleConnection *gc,
+ const char *conference_type,
+ const char *remote_user);
G_END_DECLS
============================================================
--- libpurple/protocols/jabber/google.c 54db4f757cb3e95ab92f7a957e38a0a72a9e232c
+++ libpurple/protocols/jabber/google.c 73468b6784b2a3952c16bd157bdf23624d42fc32
@@ -18,7 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
-#include <farsight/farsight-transport.h>
+#include <gst/farsight/fs-conference-iface.h>
#include "internal.h"
#include "debug.h"
@@ -49,7 +49,6 @@ typedef struct {
GoogleSessionId id;
GoogleSessionState state;
PurpleMedia *media;
- FarsightStream *stream;
JabberStream *js;
char *remote_jid;
} GoogleSession;
@@ -84,7 +83,6 @@ google_session_destroy(GoogleSession *se
g_free(session->id.initiator);
g_free(session->remote_jid);
g_object_unref(session->media);
- g_object_unref(session->stream);
g_free(session);
}
@@ -103,7 +101,7 @@ google_session_send_accept(GoogleSession
google_session_send_accept(GoogleSession *session)
{
xmlnode *sess, *desc, *payload;
- GList *codecs = farsight_stream_get_codec_intersection(session->stream);
+ GList *codecs = purple_media_get_negotiated_audio_codecs(session->media);
JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
xmlnode_set_attrib(iq->node, "to", session->remote_jid);
@@ -113,7 +111,7 @@ google_session_send_accept(GoogleSession
xmlnode_set_namespace(desc, "http://www.google.com/session/phone");
for (;codecs; codecs = codecs->next) {
- FarsightCodec *codec = (FarsightCodec*)codecs->data;
+ FsCodec *codec = (FsCodec*)codecs->data;
char id[8], clockrate[10];
payload = xmlnode_new_child(desc, "payload-type");
g_snprintf(id, sizeof(id), "%d", codec->id);
@@ -123,15 +121,15 @@ google_session_send_accept(GoogleSession
xmlnode_set_attrib(payload, "clockrate", clockrate);
}
+ fs_codec_list_destroy(codecs);
jabber_iq_send(iq);
- farsight_stream_start(session->stream);
+ gst_element_set_state(purple_media_get_audio_pipeline(session->media), GST_STATE_PLAYING);
}
static void
google_session_send_terminate(GoogleSession *session)
{
xmlnode *sess;
- GList *codecs = farsight_stream_get_codec_intersection(session->stream);
JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
xmlnode_set_attrib(iq->node, "to", session->remote_jid);
@@ -139,7 +137,6 @@ google_session_send_terminate(GoogleSess
xmlnode_insert_child(iq->node, sess);
jabber_iq_send(iq);
- farsight_stream_stop(session->stream);
google_session_destroy(session);
}
@@ -147,7 +144,6 @@ google_session_send_reject(GoogleSession
google_session_send_reject(GoogleSession *session)
{
xmlnode *sess;
- GList *codecs = farsight_stream_get_codec_intersection(session->stream);
JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
xmlnode_set_attrib(iq->node, "to", session->remote_jid);
@@ -155,17 +151,16 @@ google_session_send_reject(GoogleSession
xmlnode_insert_child(iq->node, sess);
jabber_iq_send(iq);
- farsight_stream_stop(session->stream);
google_session_destroy(session);
}
static void
-google_session_candidates_prepared (FarsightStream *stream, gchar *candidate_id, GoogleSession *session)
+google_session_candidates_prepared (PurpleMedia *media, GoogleSession *session)
{
JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
- GList *candidates = farsight_stream_get_native_candidate_list(stream);
- FarsightTransportInfo *transport;
+ GList *candidates = purple_media_get_local_audio_candidates(session->media);
+ FsCandidate *transport;
xmlnode *sess;
xmlnode *candidate;
sess = google_session_create_xmlnode(session, "candidates");
@@ -173,9 +168,9 @@ google_session_candidates_prepared (Fars
xmlnode_set_attrib(iq->node, "to", session->remote_jid);
for (;candidates;candidates = candidates->next) {
- transport = (FarsightTransportInfo*)(candidates->data);
char port[8];
char pref[8];
+ transport = (FsCandidate*)(candidates->data);
if (!strcmp(transport->ip, "127.0.0.1"))
continue;
@@ -183,7 +178,7 @@ google_session_candidates_prepared (Fars
candidate = xmlnode_new("candidate");
g_snprintf(port, sizeof(port), "%d", transport->port);
- g_snprintf(pref, sizeof(pref), "%f", transport->preference);
+ g_snprintf(pref, sizeof(pref), "%d", transport->priority);
xmlnode_set_attrib(candidate, "address", transport->ip);
xmlnode_set_attrib(candidate, "port", port);
@@ -191,10 +186,10 @@ google_session_candidates_prepared (Fars
xmlnode_set_attrib(candidate, "username", transport->username);
xmlnode_set_attrib(candidate, "password", transport->password);
xmlnode_set_attrib(candidate, "preference", pref);
- xmlnode_set_attrib(candidate, "protocol", transport->proto == FARSIGHT_NETWORK_PROTOCOL_UDP ? "udp" : "tcp");
- xmlnode_set_attrib(candidate, "type", transport->type == FARSIGHT_CANDIDATE_TYPE_LOCAL ? "local" :
- transport->type == FARSIGHT_CANDIDATE_TYPE_DERIVED ? "stun" :
- transport->type == FARSIGHT_CANDIDATE_TYPE_RELAY ? "relay" : NULL);
+ xmlnode_set_attrib(candidate, "protocol", transport->proto == FS_NETWORK_PROTOCOL_UDP ? "udp" : "tcp");
+ xmlnode_set_attrib(candidate, "type", transport->type == FS_CANDIDATE_TYPE_HOST ? "local" :
+ transport->type == FS_CANDIDATE_TYPE_PRFLX ? "stun" :
+ transport->type == FS_CANDIDATE_TYPE_RELAY ? "relay" : NULL);
xmlnode_set_attrib(candidate, "generation", "0");
xmlnode_set_attrib(candidate, "network", "0");
xmlnode_insert_child(sess, candidate);
@@ -206,30 +201,24 @@ google_session_handle_initiate(JabberStr
static void
google_session_handle_initiate(JabberStream *js, GoogleSession *session, xmlnode *packet, xmlnode *sess)
{
- PurpleMedia *media;
JabberIq *result;
- FarsightSession *fs;
GList *codecs = NULL;
xmlnode *desc_element, *codec_element;
- FarsightCodec *codec;
+ FsCodec *codec;
const char *id, *encoding_name, *clock_rate;
- int res;
if (session->state != UNINIT) {
purple_debug_error("jabber", "Received initiate for active session.\n");
- return FALSE;
+ return;
}
- fs = farsight_session_factory_make("rtp");
- if (!fs) {
- purple_debug_error("jabber", "Farsight's rtp plugin not installed");
- return FALSE;
- }
-
- session->stream = farsight_session_create_stream(fs, FARSIGHT_MEDIA_TYPE_AUDIO, FARSIGHT_STREAM_DIRECTION_BOTH);
+ session->media = purple_media_manager_create_media(purple_media_manager_get(), js->gc,
+ "fsrtpconference", session->remote_jid);
- g_object_set(G_OBJECT(session->stream), "transmitter", "libjingle", NULL);
-
+ /* "rawudp" will need to be changed to "nice" when libnice is finished */
+ purple_media_add_stream(session->media, session->remote_jid,
+ PURPLE_MEDIA_AUDIO, "rawudp");
+
desc_element = xmlnode_get_child(sess, "description");
for (codec_element = xmlnode_get_child(desc_element, "payload-type");
@@ -239,31 +228,25 @@ google_session_handle_initiate(JabberStr
id = xmlnode_get_attrib(codec_element, "id");
clock_rate = xmlnode_get_attrib(codec_element, "clockrate");
- codec = g_new0(FarsightCodec, 1);
- farsight_codec_init(codec, atoi(id), encoding_name, FARSIGHT_MEDIA_TYPE_AUDIO, clock_rate ? atoi(clock_rate) : 0);
+ codec = fs_codec_new(atoi(id), encoding_name, FS_MEDIA_TYPE_AUDIO,
+ clock_rate ? atoi(clock_rate) : 0);
codecs = g_list_append(codecs, codec);
}
- session->media = media = purple_media_manager_create_media(purple_media_manager_get(), js->gc, session->remote_jid, session->stream, NULL);
+ purple_media_set_remote_audio_codecs(session->media, session->remote_jid, codecs);
- g_signal_connect_swapped(G_OBJECT(media), "accepted", G_CALLBACK(google_session_send_accept), session);
- g_signal_connect_swapped(G_OBJECT(media), "reject", G_CALLBACK(google_session_send_reject), session);
- g_signal_connect_swapped(G_OBJECT(media), "hangup", G_CALLBACK(google_session_send_terminate), session);
+ g_signal_connect_swapped(G_OBJECT(session->media), "accepted",
+ G_CALLBACK(google_session_send_accept), session);
+ g_signal_connect_swapped(G_OBJECT(session->media), "reject",
+ G_CALLBACK(google_session_send_reject), session);
+ g_signal_connect_swapped(G_OBJECT(session->media), "hangup",
+ G_CALLBACK(google_session_send_terminate), session);
+ g_signal_connect(G_OBJECT(session->media), "candidates-prepared",
+ G_CALLBACK(google_session_candidates_prepared), session);
+ purple_media_ready(session->media);
+ fs_codec_list_destroy(codecs);
- GstElement *e = purple_media_get_audio_src(media);
- farsight_stream_set_source(session->stream, e);
-
- e = purple_media_get_audio_sink(media);
- farsight_stream_set_sink(session->stream, e);
-
- farsight_stream_prepare_transports(session->stream);
- res = farsight_stream_set_remote_codecs(session->stream, codecs);
-
- purple_media_ready(media);
-
- farsight_codec_list_destroy(codecs);
- g_signal_connect(G_OBJECT(session->stream), "new-native-candidate", G_CALLBACK(google_session_candidates_prepared), session);
result = jabber_iq_new(js, JABBER_IQ_RESULT);
jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id"));
xmlnode_set_attrib(result->node, "to", session->remote_jid);
@@ -280,24 +263,26 @@ google_session_handle_candidates(JabberS
char n[4];
for (cand = xmlnode_get_child(sess, "candidate"); cand; cand = xmlnode_get_next_twin(cand)) {
- FarsightTransportInfo *info = g_new0(FarsightTransportInfo, 1);
+ FsCandidate *info;
g_snprintf(n, sizeof(n), "S%d", name++);
- info->ip = xmlnode_get_attrib(cand, "address");
- info->port = atoi(xmlnode_get_attrib(cand, "port"));
- info->proto = !strcmp(xmlnode_get_attrib(cand, "protocol"),"udp") ? FARSIGHT_NETWORK_PROTOCOL_UDP : FARSIGHT_NETWORK_PROTOCOL_TCP;
- info->preference = atof(xmlnode_get_attrib(cand, "preference"));
- info->type = !strcmp(xmlnode_get_attrib(cand, "type"), "local") ? FARSIGHT_CANDIDATE_TYPE_LOCAL :
- !strcmp(xmlnode_get_attrib(cand, "type"), "stun") ? FARSIGHT_CANDIDATE_TYPE_DERIVED :
- !strcmp(xmlnode_get_attrib(cand, "type"), "relay") ? FARSIGHT_CANDIDATE_TYPE_RELAY : FARSIGHT_CANDIDATE_TYPE_LOCAL;
- info->candidate_id = n;
- info->username = xmlnode_get_attrib(cand, "username");
- info->password = xmlnode_get_attrib(cand, "password");
+ info = fs_candidate_new(n, FS_COMPONENT_RTP, !strcmp(xmlnode_get_attrib(cand, "type"), "local") ?
+ FS_CANDIDATE_TYPE_HOST :
+ !strcmp(xmlnode_get_attrib(cand, "type"), "stun") ?
+ FS_CANDIDATE_TYPE_PRFLX :
+ !strcmp(xmlnode_get_attrib(cand, "type"), "relay") ?
+ FS_CANDIDATE_TYPE_RELAY : FS_CANDIDATE_TYPE_HOST,
+ !strcmp(xmlnode_get_attrib(cand, "protocol"),"udp") ?
+ FS_NETWORK_PROTOCOL_UDP : FS_NETWORK_PROTOCOL_TCP,
+ xmlnode_get_attrib(cand, "address"), atoi(xmlnode_get_attrib(cand, "port")));
+
+ info->username = g_strdup(xmlnode_get_attrib(cand, "username"));
+ info->password = g_strdup(xmlnode_get_attrib(cand, "password"));
+
list = g_list_append(list, info);
}
- farsight_stream_add_remote_candidate(session->stream, list);
- g_list_foreach(list, g_free, NULL);
- g_list_free(list);
+ purple_media_add_remote_audio_candidates(session->media, session->remote_jid, list);
+ fs_candidate_list_destroy(list);
result = jabber_iq_new(js, JABBER_IQ_RESULT);
jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id"));
@@ -308,7 +293,6 @@ google_session_handle_reject(JabberStrea
static void
google_session_handle_reject(JabberStream *js, GoogleSession *session, xmlnode *packet, xmlnode *sess)
{
- farsight_stream_stop(session->stream);
purple_media_got_hangup(session->media);
google_session_destroy(session);
@@ -317,7 +301,6 @@ google_session_handle_terminate(JabberSt
static void
google_session_handle_terminate(JabberStream *js, GoogleSession *session, xmlnode *packet, xmlnode *sess)
{
- farsight_stream_stop(session->stream);
purple_media_got_hangup(session->media);
google_session_destroy(session);
@@ -346,7 +329,6 @@ jabber_google_session_parse(JabberStream
{
GoogleSession *session;
GoogleSessionId id;
- JabberIq *result;
xmlnode *session_node;
xmlnode *desc_node;
@@ -358,11 +340,11 @@ jabber_google_session_parse(JabberStream
if (!session_node)
return;
- id.id = xmlnode_get_attrib(session_node, "id");
+ id.id = (gchar*)xmlnode_get_attrib(session_node, "id");
if (!id.id)
return;
- id.initiator = xmlnode_get_attrib(session_node, "initiator");
+ id.initiator = (gchar*)xmlnode_get_attrib(session_node, "initiator");
if (!id.initiator)
return;
============================================================
--- libpurple/protocols/jabber/jabber.c 0ab12231f112cf57c2f76d4c9ffa5f57c89308da
+++ libpurple/protocols/jabber/jabber.c 9ce5f316715cf074a44c11d571b3b23f217e730b
@@ -58,6 +58,8 @@
#include "adhoccommands.h"
#include "jingle.h"
+#include <gst/farsight/fs-conference-iface.h>
+
#define JABBER_CONNECT_STEPS (js->gsc ? 9 : 5)
static PurplePlugin *my_protocol = NULL;
@@ -1240,6 +1242,16 @@ void jabber_close(PurpleConnection *gc)
{
JabberStream *js = gc->proto_data;
+#ifdef USE_FARSIGHT
+ /* Close all of the open media sessions on this stream */
+ GList *iter = jabber_jingle_session_find_by_js(js);
+
+ for (; iter; iter = iter->next) {
+ JingleSession *session = (JingleSession *)iter->data;
+ purple_media_hangup(session->media);
+ }
+#endif
+
/* Don't perform any actions on the ssl connection
* if we were forcibly disconnected because it will crash
* on some SSL backends.
@@ -1862,10 +1874,20 @@ void jabber_convo_closed(PurpleConnectio
JabberID *jid;
JabberBuddy *jb;
JabberBuddyResource *jbr;
-
+#ifdef USE_FARSIGHT
+ JingleSession *session;
+#endif
if(!(jid = jabber_id_new(who)))
return;
+#ifdef USE_FARSIGHT
+ session = jabber_jingle_session_find_by_jid(js, who);
+
+ if (session) {
+ purple_media_hangup(session->media);
+ }
+
+#endif
if((jb = jabber_buddy_find(js, who, TRUE)) &&
(jbr = jabber_buddy_find_resource(jb, jid->resource))) {
if(jbr->thread_id) {
@@ -2357,11 +2379,9 @@ jabber_session_send_accept(JingleSession
xmlnode_insert_child(result->node, jingle);
jabber_iq_send(result);
purple_debug_info("jabber", "Sent session accept, starting stream\n");
- farsight_stream_start(jabber_jingle_session_get_stream(session));
- farsight_stream_set_remote_codecs(
- jabber_jingle_session_get_stream(session),
- jabber_jingle_session_get_remote_codecs(session));
+ gst_element_set_state(purple_media_get_audio_pipeline(session->media), GST_STATE_PLAYING);
+ session->session_started = TRUE;
}
static void
@@ -2388,7 +2408,6 @@ jabber_session_send_reject(JingleSession
jabber_jingle_session_get_remote_jid(session));
xmlnode_insert_child(result->node, jingle);
jabber_iq_send(result);
- farsight_stream_stop(jabber_jingle_session_get_stream(session));
jabber_jingle_session_destroy(session);
}
@@ -2403,117 +2422,135 @@ jabber_session_send_terminate(JingleSess
jabber_jingle_session_get_remote_jid(session));
xmlnode_insert_child(result->node, jingle);
jabber_iq_send(result);
- farsight_stream_stop(jabber_jingle_session_get_stream(session));
jabber_jingle_session_destroy(session);
}
/* callback called when new local transport candidate(s) are available on the
Farsight stream */
static void
-jabber_session_candidates_prepared(FarsightStream *stream, gchar *candidate_id,
- JingleSession *session)
+jabber_session_candidates_prepared(PurpleMedia *media, JingleSession *session)
{
- /* create transport-info package */
- JabberIq *result = jabber_iq_new(jabber_jingle_session_get_js(session),
- JABBER_IQ_SET);
- xmlnode *jingle = jabber_jingle_session_create_transport_info(session,
- candidate_id);
- purple_debug_info("jabber", "jabber_session_candidates_prepared called for candidate_id = %s\n",
- candidate_id);
- xmlnode_set_attrib(result->node, "to",
- jabber_jingle_session_get_remote_jid(session));
-
- xmlnode_insert_child(result->node, jingle);
- jabber_iq_send(result);
+ if (!jabber_jingle_session_is_initiator(session)) {
+ /* create transport-info package */
+ JabberIq *result = jabber_iq_new(jabber_jingle_session_get_js(session),
+ JABBER_IQ_SET);
+ xmlnode *jingle = jabber_jingle_session_create_transport_info(session);
+ purple_debug_info("jabber", "jabber_session_candidates_prepared: %d candidates\n",
+ g_list_length(purple_media_get_local_audio_candidates(session->media)));
+ xmlnode_set_attrib(result->node, "to",
+ jabber_jingle_session_get_remote_jid(session));
+
+ xmlnode_insert_child(result->node, jingle);
+ jabber_iq_send(result);
+ }
}
/* callback called when a pair of transport candidates (local and remote)
has been established */
static void
-jabber_session_candidate_pair_established(FarsightStream *stream,
- gchar *native_candidate_id,
- gchar *remote_candidate_id,
- JingleSession *session)
+jabber_session_candidate_pair_established(PurpleMedia *media,
+ FsCandidate *native_candidate,
+ FsCandidate *remote_candidate,
+ JingleSession *session)
{
- purple_debug_info("jabber", "jabber_candidate_pair_established called");
+ purple_debug_info("jabber", "jabber_candidate_pair_established called\n");
/* if we are the initiator, we should send a content-modify message */
if (jabber_jingle_session_is_initiator(session)) {
- purple_debug_info("jabber",
- "we are the initiator, let's send conten-modify\n");
- JabberIq *result = jabber_iq_new(jabber_jingle_session_get_js(session),
- JABBER_IQ_SET);
+ JabberIq *result;
+ xmlnode *jingle;
+
+ purple_debug_info("jabber", "we are the initiator, let's send content-modify\n");
+
+ result = jabber_iq_new(jabber_jingle_session_get_js(session), JABBER_IQ_SET);
+
/* shall change this to a "content-replace" */
- xmlnode *jingle =
+ jingle =
jabber_jingle_session_create_content_replace(session,
- native_candidate_id,
- remote_candidate_id);
+ native_candidate,
+ remote_candidate);
xmlnode_set_attrib(result->node, "to",
jabber_jingle_session_get_remote_jid(session));
xmlnode_insert_child(result->node, jingle);
jabber_iq_send(result);
}
- /*
- farsight_stream_set_active_candidate_pair(stream, native_candidate_id,
- remote_candidate_id);
- */
}
+static void
+jabber_initiate_media_internal(JingleSession *session, const char *initiator, const char *remote_jid)
+{
+ PurpleMedia *media = NULL;
-PurpleMedia *jabber_initiate_media(PurpleConnection *gc, const char *who,
+ media = purple_media_manager_create_media(purple_media_manager_get(),
+ session->js->gc, "fsrtpconference", remote_jid);
+ /* this will need to be changed to "nice" once the libnice transmitter is finished */
+ purple_media_add_stream(media, remote_jid, PURPLE_MEDIA_AUDIO, "rawudp");
+
+ jabber_jingle_session_set_remote_jid(session, remote_jid);
+ jabber_jingle_session_set_initiator(session, initiator);
+ jabber_jingle_session_set_media(session, media);
+
+ /* connect callbacks */
+ g_signal_connect_swapped(G_OBJECT(media), "accepted",
+ G_CALLBACK(jabber_session_send_accept), session);
+ g_signal_connect_swapped(G_OBJECT(media), "reject",
+ G_CALLBACK(jabber_session_send_reject), session);
+ g_signal_connect_swapped(G_OBJECT(media), "hangup",
+ G_CALLBACK(jabber_session_send_terminate), session);
+ g_signal_connect(G_OBJECT(media), "candidates-prepared",
+ G_CALLBACK(jabber_session_candidates_prepared), session);
+ g_signal_connect(G_OBJECT(media), "candidate-pair",
+ G_CALLBACK(jabber_session_candidate_pair_established), session);
+
+ purple_media_ready(media);
+}
+
+static void
+jabber_session_initiate_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
+{
+ const char *from = xmlnode_get_attrib(packet, "from");
+ JingleSession *session = jabber_jingle_session_find_by_jid(js, from);
+ PurpleMedia *media = session->media;
+ JabberIq *result;
+ xmlnode *jingle;
+
+ if (!strcmp(xmlnode_get_attrib(packet, "type"), "error")) {
+ purple_media_got_hangup(media);
+ return;
+ }
+
+ /* catch errors */
+ if (xmlnode_get_child(packet, "error")) {
+ purple_media_got_hangup(media);
+ return;
+ }
+
+ /* create transport-info package */
+ result = jabber_iq_new(jabber_jingle_session_get_js(session), JABBER_IQ_SET);
+ jingle = jabber_jingle_session_create_transport_info(session);
+ purple_debug_info("jabber", "jabber_session_candidates_prepared: %d candidates\n",
+ g_list_length(purple_media_get_local_audio_candidates(session->media)));
+ xmlnode_set_attrib(result->node, "to",
+ jabber_jingle_session_get_remote_jid(session));
+
+ xmlnode_insert_child(result->node, jingle);
+ jabber_iq_send(result);
+}
+
+PurpleMedia *
+jabber_initiate_media(PurpleConnection *gc, const char *who,
PurpleMediaStreamType type)
{
/* create content negotiation */
JabberStream *js = gc->proto_data;
JabberIq *request = jabber_iq_new(js, JABBER_IQ_SET);
- xmlnode *jingle, *content, *description, *payload_type, *transport;
- FarsightSession *fs = NULL;
- FarsightStream *audio = NULL; /* only audio for now... */
+ xmlnode *jingle, *content, *description, *transport;
GList *codecs;
- GList *codec_iter = NULL;
- FarsightCodec *codec = NULL;
- PurpleMedia *media = NULL;
JingleSession *session;
JabberBuddy *jb;
JabberBuddyResource *jbr;
- char id[10];
- char clock_rate[10];
- char channels[10];
- char jid[256];
- char me[256];
-
- /* for debug */
- char *output;
- int len;
-
- /* setup stream */
- fs = farsight_session_factory_make("rtp");
- if (fs == NULL) {
- purple_debug_error("jabber", "Farsight's rtp plugin not installed");
- return NULL;
- }
-
- /* check media stream type, and so on... */
- /* only do audio for now... */
-
- /* get stuff from Farsight... */
- audio = farsight_session_create_stream(fs, FARSIGHT_MEDIA_TYPE_AUDIO,
- FARSIGHT_STREAM_DIRECTION_BOTH);
- g_object_set(G_OBJECT(audio), "transmitter", "libjingle", NULL);
-
- purple_debug_info("jabber", "Getting local codecs\n");
- codecs = farsight_stream_get_local_codecs(audio);
- purple_debug_info("jabber", "number of codecs: %d\n", g_list_length(codecs));
-
- if (audio == NULL) {
- purple_debug_error("jabber", "Unable to create Farsight stream for audio");
- /* destroy FarsightSession? */
- return NULL;
- }
-
- media = purple_media_manager_create_media(purple_media_manager_get(),
- gc, who, audio, NULL);
- purple_debug_info("jabber", "After purple_media_manager_create_media\n");
+ char *jid = NULL, *me = NULL;
+
/* construct JID to send to */
jb = jabber_buddy_find(js, who, FALSE);
if (!jb) {
@@ -2524,42 +2561,24 @@ PurpleMedia *jabber_initiate_media(Purpl
if (!jbr) {
purple_debug_error("jabber", "Could not find buddy's resource\n");
}
+
+ if ((strchr(who, '/') == NULL) && jbr && (jbr->name != NULL)) {
+ jid = g_strdup_printf("%s/%s", who, jbr->name);
+ } else {
+ jid = g_strdup(who);
+ }
- g_snprintf(jid, 255, "%s/%s", who, jbr->name);
-
session = jabber_jingle_session_create(js);
- jabber_jingle_session_set_remote_jid(session, jid);
/* set ourselves as initiator */
- g_snprintf(me, sizeof(me), "%s@%s/%s", js->user->node, js->user->domain,
- js->user->resource);
- jabber_jingle_session_set_initiator(session, me);
-
- jabber_jingle_session_set_stream(session, audio);
- jabber_jingle_session_set_media(session, media);
-
- g_signal_connect_swapped(G_OBJECT(media), "accepted",
- G_CALLBACK(jabber_session_send_accept), session);
- g_signal_connect_swapped(G_OBJECT(media), "reject",
- G_CALLBACK(jabber_session_send_reject), session);
- g_signal_connect_swapped(G_OBJECT(media), "hangup",
- G_CALLBACK(jabber_session_send_terminate), session);
-
- GstElement *e = purple_media_get_audio_src(media);
- farsight_stream_set_source(jabber_jingle_session_get_stream(session), e);
- e = purple_media_get_audio_sink(media);
- farsight_stream_set_sink(jabber_jingle_session_get_stream(session), e);
-
- farsight_stream_prepare_transports(audio);
- /* callback for new native (local) transport candidates for the stream */
- g_signal_connect(G_OBJECT(audio),
- "new-native-candidate",
- G_CALLBACK(jabber_session_candidates_prepared), session);
- /* callback for new active candidate pair (established connection) */
- g_signal_connect(G_OBJECT(audio),
- "new-active-candidate-pair",
- G_CALLBACK(jabber_session_candidate_pair_established),
- session);
-
+ me = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain, js->user->resource);
+
+ jabber_initiate_media_internal(session, me, jid);
+
+ g_free(jid);
+ g_free(me);
+
+ codecs = purple_media_get_local_audio_codecs(session->media);
+
/* create request */
xmlnode_set_attrib(request->node, "to",
@@ -2568,40 +2587,27 @@ PurpleMedia *jabber_initiate_media(Purpl
xmlnode_set_namespace(jingle, "urn:xmpp:tmp:jingle");
xmlnode_set_attrib(jingle, "action", "session-initiate");
/* get our JID and a session id... */
- xmlnode_set_attrib(jingle, "initiator", me);
+ xmlnode_set_attrib(jingle, "initiator", jabber_jingle_session_get_initiator(session));
xmlnode_set_attrib(jingle, "sid", jabber_jingle_session_get_id(session));
content = xmlnode_new_child(jingle, "content");
xmlnode_set_attrib(content, "name", "audio-content");
xmlnode_set_attrib(content, "profile", "RTP/AVP");
-
- description = xmlnode_new_child(content, "description");
- xmlnode_set_namespace(description, "urn:xmpp:tmp:jingle:apps:audio-rtp");
-
- /* create payload-type nodes */
- purple_debug_info("jabber", "Generating payload_type elements\n");
- for (; codecs ; codecs = codecs->next) {
- codec = (FarsightCodec *) codecs->data;
- purple_debug_info("jabber", "Generating payload_type for (%d) %s\n",
- codec->id, codec->encoding_name);
- sprintf(id, "%d", codec->id);
- sprintf(clock_rate, "%d", codec->clock_rate);
- sprintf(channels, "%d", codec->channels);
-
- payload_type = xmlnode_new_child(description, "payload-type");
- xmlnode_set_attrib(payload_type, "id", id);
- xmlnode_set_attrib(payload_type, "name", codec->encoding_name);
- xmlnode_set_attrib(payload_type, "clockrate", clock_rate);
- xmlnode_set_attrib(payload_type, "channels", channels);
- }
-
+
+ description = jabber_jingle_session_create_description(session);
+ xmlnode_insert_child(content, description);
+
transport = xmlnode_new_child(content, "transport");
- xmlnode_set_namespace(transport, "urn:xmpp:tmp:jingle:transports:ice-tcp");
-
+ xmlnode_set_namespace(transport, "urn:xmpp:tmp:jingle:transports:ice-udp");
+
+ jabber_iq_set_callback(request, jabber_session_initiate_result_cb, NULL);
+
/* send request to other part */
jabber_iq_send(request);
- return media;
+ fs_codec_list_destroy(codecs);
+
+ return session->media;
}
gboolean jabber_can_do_media(PurpleConnection *gc, const char *who,
@@ -2620,11 +2626,10 @@ jabber_handle_session_accept(JabberStrea
const char *sid = xmlnode_get_attrib(jingle, "sid");
const char *action = xmlnode_get_attrib(jingle, "action");
JingleSession *session = jabber_jingle_session_find_by_id(sid);
- FarsightStream *stream = jabber_jingle_session_get_stream(session);
GList *remote_codecs = NULL;
GList *remote_transports = NULL;
- GList *codec_intersection = NULL;
- FarsightCodec *top = NULL;
+ GList *codec_intersection;
+ FsCodec *top = NULL;
xmlnode *description = NULL;
xmlnode *transport = NULL;
@@ -2634,7 +2639,7 @@ jabber_handle_session_accept(JabberStrea
jabber_jingle_session_get_remote_jid(session));
jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id"));
- description = xmlnode_get_child(jingle, "description");
+ description = xmlnode_get_child(content, "description");
transport = xmlnode_get_child(content, "transport");
/* fetch codecs from remote party */
@@ -2650,27 +2655,29 @@ jabber_handle_session_accept(JabberStrea
purple_debug_info("jabber", "Setting remote codecs on stream\n");
- farsight_stream_set_remote_codecs(stream, remote_codecs);
- if (!strcmp(action, "session-accept")) {
- jabber_jingle_session_set_remote_codecs(session, remote_codecs);
- }
+ purple_media_set_remote_audio_codecs(session->media,
+ jabber_jingle_session_get_remote_jid(session),
+ remote_codecs);
- codec_intersection = farsight_stream_get_codec_intersection(stream);
+ codec_intersection = purple_media_get_negotiated_audio_codecs(session->media);
purple_debug_info("jabber", "codec_intersection contains %d elems\n",
g_list_length(codec_intersection));
/* get the top codec */
if (g_list_length(codec_intersection) > 0) {
- top = (FarsightCodec *) codec_intersection->data;
- purple_debug_info("jabber", "setting active codec on stream = %d\n",
+ top = (FsCodec *) codec_intersection->data;
+ purple_debug_info("jabber", "Found a suitable codec on stream = %d\n",
top->id);
- farsight_stream_set_active_codec(stream, top->id);
+
/* we have found a suitable codec, but we will not start the stream
just yet, wait for transport negotiation to complete... */
}
/* if we also got transport candidates, add them to our streams
list of known remote candidates */
if (g_list_length(remote_transports) > 0) {
- farsight_stream_set_remote_candidate_list(stream, remote_transports);
+ purple_media_add_remote_audio_candidates(session->media,
+ jabber_jingle_session_get_remote_jid(session),
+ remote_transports);
+ fs_candidate_list_destroy(remote_transports);
}
if (g_list_length(codec_intersection) == 0 &&
g_list_length(remote_transports)) {
@@ -2685,10 +2692,12 @@ jabber_handle_session_accept(JabberStrea
if (!strcmp(action, "session-accept")) {
purple_media_got_accept(jabber_jingle_session_get_media(session));
purple_debug_info("jabber", "Got session-accept, starting stream\n");
- farsight_stream_start(jabber_jingle_session_get_stream(session));
+ gst_element_set_state(purple_media_get_audio_pipeline(session->media), GST_STATE_PLAYING);
}
jabber_iq_send(result);
+
+ session->session_started = TRUE;
}
void
@@ -2707,11 +2716,10 @@ jabber_handle_session_terminate(JabberSt
/* maybe we should look at the reasoncode to determine if it was
a hangup or a reject, and call different callbacks to purple_media */
+ gst_element_set_state(purple_media_get_audio_pipeline(session->media), GST_STATE_NULL);
-
purple_media_got_hangup(jabber_jingle_session_get_media(session));
jabber_iq_send(result);
- farsight_stream_stop(jabber_jingle_session_get_stream(session));
jabber_jingle_session_destroy(session);
}
@@ -2726,6 +2734,9 @@ jabber_handle_session_candidates(JabberS
const char *sid = xmlnode_get_attrib(jingle, "sid");
JingleSession *session = jabber_jingle_session_find_by_id(sid);
+ if(!session)
+ purple_debug_error("jabber", "jabber_handle_session_candidates couldn't find session\n");
+
/* send acknowledement */
xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id"));
xmlnode_set_attrib(result->node, "to", xmlnode_get_attrib(packet, "from"));
@@ -2733,10 +2744,10 @@ jabber_handle_session_candidates(JabberS
/* add candidates to our list of remote candidates */
if (g_list_length(remote_candidates) > 0) {
- farsight_stream_add_remote_candidate(
- jabber_jingle_session_get_stream(session),
- remote_candidates);
- jabber_jingle_session_add_remote_candidate(session, remote_candidates);
+ purple_media_add_remote_audio_candidates(session->media,
+ xmlnode_get_attrib(packet, "from"),
+ remote_candidates);
+ fs_candidate_list_destroy(remote_candidates);
}
}
@@ -2744,25 +2755,28 @@ jabber_handle_session_content_replace(Ja
void
jabber_handle_session_content_replace(JabberStream *js, xmlnode *packet)
{
- JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT);
- JabberIq *accept = jabber_iq_new(js, JABBER_IQ_SET);
- xmlnode *content_accept = NULL;
xmlnode *jingle = xmlnode_get_child(packet, "jingle");
const char *sid = xmlnode_get_attrib(jingle, "sid");
JingleSession *session = jabber_jingle_session_find_by_id(sid);
- /* send acknowledement */
- xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id"));
- xmlnode_set_attrib(result->node, "to", xmlnode_get_attrib(packet, "from"));
- jabber_iq_send(result);
+ if (!jabber_jingle_session_is_initiator(session) && session->session_started) {
+ JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT);
+ JabberIq *accept = jabber_iq_new(js, JABBER_IQ_SET);
+ xmlnode *content_accept = NULL;
- /* send content-accept */
- content_accept = jabber_jingle_session_create_content_accept(session);
- xmlnode_set_attrib(accept->node, "id", xmlnode_get_attrib(packet, "id"));
- xmlnode_set_attrib(accept->node, "to", xmlnode_get_attrib(packet, "from"));
- xmlnode_insert_child(accept->node, content_accept);
+ /* send acknowledement */
+ xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id"));
+ xmlnode_set_attrib(result->node, "to", xmlnode_get_attrib(packet, "from"));
+ jabber_iq_send(result);
- jabber_iq_send(accept);
+ /* send content-accept */
+ content_accept = jabber_jingle_session_create_content_accept(session);
+ xmlnode_set_attrib(accept->node, "id", xmlnode_get_attrib(packet, "id"));
+ xmlnode_set_attrib(accept->node, "to", xmlnode_get_attrib(packet, "from"));
+ xmlnode_insert_child(accept->node, content_accept);
+
+ jabber_iq_send(accept);
+ }
}
void
@@ -2772,33 +2786,25 @@ jabber_handle_session_initiate(JabberStr
xmlnode *jingle = xmlnode_get_child(packet, "jingle");
xmlnode *content = NULL;
xmlnode *description = NULL;
- char *sid = NULL;
- char *initiator = NULL;
+ const char *sid = NULL;
+ const char *initiator = NULL;
GList *codecs = NULL;
- FarsightSession *fs = NULL;
- FarsightStream *audio = NULL;
- PurpleMedia *media = NULL;
JabberIq *result = NULL;
- JabberIq *content_accept = NULL;
- xmlnode *content_accept_jingle = NULL;
- GList *codec_intersection = NULL;
- int res;
-
if (!jingle) {
purple_debug_error("jabber", "Malformed request");
return;
}
sid = xmlnode_get_attrib(jingle, "sid");
- //initiator = xmlnode_get_attrib(jingle, "initiator");
- initiator = xmlnode_get_attrib(packet, "from");
+ initiator = xmlnode_get_attrib(jingle, "initiator");
+
+ if (jabber_jingle_session_find_by_id(sid)) {
+ /* This should only happen if you start a session with yourself */
+ purple_debug_error("jabber", "Jingle session with id={%s} already exists\n", sid);
+ return;
+ }
session = jabber_jingle_session_create_by_id(js, sid);
- jabber_jingle_session_set_remote_jid(session,
- xmlnode_get_attrib(packet, "from"));
- /* set "from" as iniator (we are responder) */
- jabber_jingle_session_set_initiator(session,
- xmlnode_get_attrib(packet, "from"));
/* init media */
content = xmlnode_get_child(jingle, "content");
@@ -2811,92 +2817,21 @@ jabber_handle_session_initiate(JabberStr
description = xmlnode_get_child(content, "description");
if (!description) {
- purple_debug_error("jabber", "content tag must contain description tag");
+ purple_debug_error("jabber", "content tag must contain description tag\n");
/* we should create an error iq here */
return;
}
- codecs = jabber_jingle_get_codecs(description);
+ jabber_initiate_media_internal(session, initiator, initiator);
- fs = farsight_session_factory_make("rtp");
- if (!fs) {
- purple_debug_error("jabber",
- "Could not initialize Farsight's RTP plugin");
- return;
- }
+ codecs = jabber_jingle_get_codecs(description);
- audio = farsight_session_create_stream(fs,
- FARSIGHT_MEDIA_TYPE_AUDIO,
- FARSIGHT_STREAM_DIRECTION_BOTH);
+ purple_media_set_remote_audio_codecs(session->media, initiator, codecs);
- g_object_set(G_OBJECT(audio), "transmitter", "libjingle", NULL);
-
- media = purple_media_manager_create_media(purple_media_manager_get(),
- js->gc, initiator, audio, NULL);
- jabber_jingle_session_set_media(session, media);
- jabber_jingle_session_set_stream(session, audio);
-
-
- g_signal_connect_swapped(G_OBJECT(media), "accepted",
- G_CALLBACK(jabber_session_send_accept), session);
- g_signal_connect_swapped(G_OBJECT(media), "reject",
- G_CALLBACK(jabber_session_send_reject), session);
- g_signal_connect_swapped(G_OBJECT(media), "hangup",
- G_CALLBACK(jabber_session_send_terminate), session);
-
-
- GstElement *e = purple_media_get_audio_src(media);
- farsight_stream_set_source(jabber_jingle_session_get_stream(session), e);
-
- e = purple_media_get_audio_sink(media);
- farsight_stream_set_sink(jabber_jingle_session_get_stream(session), e);
-
- farsight_stream_prepare_transports(jabber_jingle_session_get_stream(session));
- /* For some reason Farsight starts the stream immediatly when calling
- farsight_stream_set_remote_codecs, before having called farsight_stream_start
- As a "workaround" (maybe this gets fixed in FS2) I'll store the list in
- the session to call it later when accepting the call */
- /*
- res =
- farsight_stream_set_remote_codecs(jabber_jingle_session_get_stream(session),
- codecs);
- */
- jabber_jingle_session_set_remote_codecs(session, codecs);
-
- purple_media_ready(media);
-
- /* We store the remote candidates in the session object... */
- /*
- farsight_codec_list_destroy(codecs);
- */
-
- /* callback for new native (local) transport candidates for the stream */
- g_signal_connect(G_OBJECT(jabber_jingle_session_get_stream(session)),
- "new-native-candidate",
- G_CALLBACK(jabber_session_candidates_prepared), session);
- /* callback for new active candidate pair (established connection) */
- g_signal_connect(G_OBJECT(jabber_jingle_session_get_stream(session)),
- "new-active-candidate-pair",
- G_CALLBACK(jabber_session_candidate_pair_established),
- session);
-
result = jabber_iq_new(js, JABBER_IQ_RESULT);
jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id"));
xmlnode_set_attrib(result->node, "to", xmlnode_get_attrib(packet, "from"));
jabber_iq_send(result);
-
- /* should send a content-accept */
- /* It crashes after this gets sent, also the id of this iq is set to
- "purple0", that seems odd... maybe I'm making some mistake here... */
- /*
- content_accept = jabber_iq_new(jabber_jingle_session_get_stream(session),
- JABBER_IQ_SET);
- content_accept_jingle = jabber_jingle_session_create_content_accept(session);
- xmlnode_set_attrib(content_accept->node, "to",
- jabber_jingle_session_get_remote_jid(session));
- xmlnode_insert_child(content_accept->node, content_accept_jingle);
- jabber_iq_send(content_accept);
- */
}
#endif
============================================================
--- libpurple/protocols/jabber/jingle.c 19b79ccb7c7e46ad8d26aeb93371ea33fc06e51c
+++ libpurple/protocols/jabber/jingle.c 5ea56e39742f641ca62cd551c502586ea30ad603
@@ -28,8 +28,7 @@
#ifdef USE_FARSIGHT
-#include <farsight/farsight.h>
-#include <farsight/farsight-transport.h>
+#include <gst/farsight/fs-candidate.h>
/* keep a hash table of JingleSessions */
static GHashTable *sessions = NULL;
@@ -66,10 +65,9 @@ jabber_jingle_session_create_internal(Ja
purple_debug_info("jingle", "inserting session with key: %s into table\n",
sess->id);
g_hash_table_insert(sessions, sess->id, sess);
-
- sess->remote_candidates = NULL;
- sess->remote_codecs = NULL;
-
+
+ sess->session_started = FALSE;
+
return sess;
}
@@ -106,8 +104,6 @@ jabber_jingle_session_destroy(JingleSess
{
g_hash_table_remove(sessions, sess->id);
g_free(sess->id);
- farsight_codec_list_destroy(sess->remote_codecs);
- g_list_free(sess->remote_candidates);
g_free(sess);
}
@@ -115,20 +111,55 @@ jabber_jingle_session_find_by_id(const c
jabber_jingle_session_find_by_id(const char *id)
{
purple_debug_info("jingle", "find_by_id %s\n", id);
- purple_debug_info("jingle", "hash table: %lx\n", sessions);
+ purple_debug_info("jingle", "hash table: %p\n", sessions);
purple_debug_info("jingle", "hash table size %d\n",
g_hash_table_size(sessions));
- purple_debug_info("jingle", "lookup: %lx\n", g_hash_table_lookup(sessions, id));
+ purple_debug_info("jingle", "lookup: %p\n", g_hash_table_lookup(sessions, id));
return (JingleSession *) g_hash_table_lookup(sessions, id);
}
GList *
+jabber_jingle_session_find_by_js(JabberStream *js)
+{
+ GList *values = g_hash_table_get_values(sessions);
+ GList *iter = values;
+ GList *found = NULL;
+
+ for (; iter; iter = iter->next) {
+ JingleSession *session = (JingleSession *)iter->data;
+ if (session->js == js) {
+ found = g_list_prepend(found, session);
+ }
+ }
+
+ g_list_free(values);
+ return found;
+}
+
+JingleSession *jabber_jingle_session_find_by_jid(JabberStream *js, const char *jid)
+{
+ GList *values = g_hash_table_get_values(sessions);
+ GList *iter = values;
+
+ for (; iter; iter = iter->next) {
+ JingleSession *session = (JingleSession *)iter->data;
+ if (session->js == js && !strcmp(jid, session->remote_jid)) {
+ g_list_free(values);
+ return session;
+ }
+ }
+
+ g_list_free(values);
+ return NULL;
+}
+
+GList *
jabber_jingle_get_codecs(const xmlnode *description)
{
GList *codecs = NULL;
xmlnode *codec_element = NULL;
const char *encoding_name,*id, *clock_rate;
- FarsightCodec *codec;
+ FsCodec *codec;
for (codec_element = xmlnode_get_child(description, "payload-type") ;
codec_element ;
@@ -137,10 +168,9 @@ jabber_jingle_get_codecs(const xmlnode *
id = xmlnode_get_attrib(codec_element, "id");
clock_rate = xmlnode_get_attrib(codec_element, "clockrate");
- codec = g_new0(FarsightCodec, 1);
- farsight_codec_init(codec, atoi(id), encoding_name,
- FARSIGHT_MEDIA_TYPE_AUDIO,
- clock_rate ? atoi(clock_rate) : 0);
+ codec = fs_codec_new(atoi(id), encoding_name,
+ FS_MEDIA_TYPE_AUDIO,
+ clock_rate ? atoi(clock_rate) : 0);
codecs = g_list_append(codecs, codec);
}
return codecs;
@@ -151,48 +181,31 @@ jabber_jingle_get_candidates(const xmlno
{
GList *candidates = NULL;
xmlnode *candidate = NULL;
- FarsightTransportInfo *ti;
+ FsCandidate *c;
for (candidate = xmlnode_get_child(transport, "candidate") ;
candidate ;
candidate = xmlnode_get_next_twin(candidate)) {
const char *type = xmlnode_get_attrib(candidate, "type");
- ti = g_new0(FarsightTransportInfo, 1);
- ti->component = atoi(xmlnode_get_attrib(candidate, "component"));
- ti->ip = xmlnode_get_attrib(candidate, "ip");
- ti->port = atoi(xmlnode_get_attrib(candidate, "port"));
- ti->proto = strcmp(xmlnode_get_attrib(candidate, "protocol"),
+ c = fs_candidate_new(xmlnode_get_attrib(candidate, "component"),
+ atoi(xmlnode_get_attrib(candidate, "component")),
+ strcmp(type, "host") == 0 ?
+ FS_CANDIDATE_TYPE_HOST :
+ strcmp(type, "prflx") == 0 ?
+ FS_CANDIDATE_TYPE_PRFLX :
+ FS_CANDIDATE_TYPE_RELAY,
+ strcmp(xmlnode_get_attrib(candidate, "protocol"),
"udp") == 0 ?
- FARSIGHT_NETWORK_PROTOCOL_UDP :
- FARSIGHT_NETWORK_PROTOCOL_TCP;
- /* it seems Farsight RTP doesn't handle this correctly right now */
- ti->username = xmlnode_get_attrib(candidate, "ufrag");
- ti->password = xmlnode_get_attrib(candidate, "pwd");
- /* not quite sure about this */
- ti->type = strcmp(type, "host") == 0 ?
- FARSIGHT_CANDIDATE_TYPE_LOCAL :
- strcmp(type, "prflx") == 0 ?
- FARSIGHT_CANDIDATE_TYPE_DERIVED :
- FARSIGHT_CANDIDATE_TYPE_RELAY;
-
- candidates = g_list_append(candidates, ti);
+ FS_NETWORK_PROTOCOL_UDP :
+ FS_NETWORK_PROTOCOL_TCP,
+ xmlnode_get_attrib(candidate, "ip"),
+ atoi(xmlnode_get_attrib(candidate, "port")));
+ candidates = g_list_append(candidates, c);
}
return candidates;
}
-FarsightStream *
-jabber_jingle_session_get_stream(const JingleSession *sess)
-{
- return sess->stream;
-}
-
-void
-jabber_jingle_session_set_stream(JingleSession *sess, FarsightStream *stream)
-{
- sess->stream = stream;
-}
-
PurpleMedia *
jabber_jingle_session_get_media(const JingleSession *sess)
{
@@ -237,36 +250,6 @@ jabber_jingle_session_is_initiator(const
return sess->is_initiator;
}
-void
-jabber_jingle_session_add_remote_candidate(JingleSession *sess,
- const GList *candidate)
-{
- /* the length of the candidate list should be 1... */
- GList *cand = candidate;
- for (; cand ; cand = cand->next) {
- purple_debug_info("jingle", "Adding remote candidate with id = %s\n",
- ((FarsightTransportInfo *) cand->data)->candidate_id);
- sess->remote_candidates = g_list_append(sess->remote_candidates,
- cand->data);
- }
-}
-
-static GList *
-jabber_jingle_session_get_remote_candidate(const JingleSession *sess,
- const gchar *id)
-{
- GList *candidates = NULL;
- GList *find = sess->remote_candidates;
- for (; find ; find = find->next) {
- const FarsightTransportInfo *candidate =
- (FarsightTransportInfo *) find->data;
- if (!strcmp(candidate->candidate_id, id)) {
- candidates = g_list_append(candidates, (void *) candidate);
- }
- }
- return candidates;
-}
-
static xmlnode *
jabber_jingle_session_create_jingle_element(const JingleSession *sess,
const char *action)
@@ -301,32 +284,105 @@ jabber_jingle_session_create_terminate(c
return jingle;
}
-static xmlnode *
+xmlnode *
jabber_jingle_session_create_description(const JingleSession *sess)
{
- GList *codecs =
- farsight_stream_get_local_codecs(jabber_jingle_session_get_stream(sess));
-
+ GList *codecs = purple_media_get_local_audio_codecs(sess->media);
xmlnode *description = xmlnode_new("description");
+
xmlnode_set_namespace(description, "urn:xmpp:tmp:jingle:apps:audio-rtp");
/* get codecs */
for (; codecs ; codecs = codecs->next) {
- FarsightCodec *codec = (FarsightCodec*)codecs->data;
- char id[8], clockrate[10];
+ FsCodec *codec = (FsCodec*)codecs->data;
+ char id[8], clockrate[10], channels[10];
xmlnode *payload = xmlnode_new_child(description, "payload-type");
g_snprintf(id, sizeof(id), "%d", codec->id);
g_snprintf(clockrate, sizeof(clockrate), "%d", codec->clock_rate);
+ g_snprintf(channels, sizeof(channels), "%d", codec->channels);
xmlnode_set_attrib(payload, "name", codec->encoding_name);
xmlnode_set_attrib(payload, "id", id);
xmlnode_set_attrib(payload, "clockrate", clockrate);
+ xmlnode_set_attrib(payload, "channels", channels);
}
+ fs_codec_list_destroy(codecs);
return description;
}
+static guint
+jabber_jingle_get_priority(guint type, guint network)
+{
+ switch (type) {
+ case FS_CANDIDATE_TYPE_HOST:
+ return network == 0 ? 4096 : network == 1 ? 2048 : 1024;
+ break;
+ case FS_CANDIDATE_TYPE_PRFLX:
+ return 126;
+ break;
+ case FS_CANDIDATE_TYPE_RELAY:
+ return 100;
+ break;
+ default:
+ return 0; /* unknown type, should not happen */
+ }
+}
+
+static xmlnode *
+jabber_jingle_session_create_candidate_info(FsCandidate *c, FsCandidate *remote)
+{
+ char port[8];
+ char prio[8];
+ char component[8];
+ xmlnode *candidate = NULL;
+
+ candidate = xmlnode_new("candidate");
+
+ g_snprintf(port, sizeof(port), "%d", c->port);
+ g_snprintf(prio, sizeof(prio), "%d",
+ jabber_jingle_get_priority(c->type, 0));
+ g_snprintf(component, sizeof(component), "%d", c->component_id);
+
+ xmlnode_set_attrib(candidate, "component", component);
+ xmlnode_set_attrib(candidate, "foundation", "1"); /* what about this? */
+ xmlnode_set_attrib(candidate, "generation", "0"); /* ? */
+ xmlnode_set_attrib(candidate, "ip", c->ip);
+ xmlnode_set_attrib(candidate, "network", "0"); /* ? */
+ xmlnode_set_attrib(candidate, "port", port);
+ xmlnode_set_attrib(candidate, "priority", prio); /* Is this correct? */
+ xmlnode_set_attrib(candidate, "protocol",
+ c->proto == FS_NETWORK_PROTOCOL_UDP ?
+ "udp" : "tcp");
+ if (c->username)
+ xmlnode_set_attrib(candidate, "ufrag", c->username);
+ if (c->password)
+ xmlnode_set_attrib(candidate, "pwd", c->password);
+
+ xmlnode_set_attrib(candidate, "type",
+ c->type == FS_CANDIDATE_TYPE_HOST ?
+ "host" :
+ c->type == FS_CANDIDATE_TYPE_PRFLX ?
+ "prflx" :
+ c->type == FS_CANDIDATE_TYPE_RELAY ?
+ "relay" : NULL);
+
+ /* relay */
+ if (c->type == FS_CANDIDATE_TYPE_RELAY) {
+ /* set rel-addr and rel-port? How? */
+ }
+
+ if (remote) {
+ char remote_port[8];
+ g_snprintf(remote_port, sizeof(remote_port), "%d", remote->port);
+ xmlnode_set_attrib(candidate, "rem-addr", remote->ip);
+ xmlnode_set_attrib(candidate, "rem-port", remote_port);
+ }
+
+ return candidate;
+}
+
/* split into two separate methods, one to generate session-accept
(includes codecs) and one to generate transport-info (includes transports
candidates) */
@@ -337,6 +393,8 @@ jabber_jingle_session_create_session_acc
jabber_jingle_session_create_jingle_element(sess, "session-accept");
xmlnode *content = NULL;
xmlnode *description = NULL;
+ xmlnode *transport = NULL;
+ xmlnode *candidate = NULL;
content = xmlnode_new_child(jingle, "content");
@@ -345,199 +403,82 @@ jabber_jingle_session_create_session_acc
xmlnode_set_attrib(content, "profile", "RTP/AVP");
description = jabber_jingle_session_create_description(sess);
- xmlnode_insert_child(jingle, description);
-
+ xmlnode_insert_child(content, description);
+
+ transport = xmlnode_new_child(content, "transport");
+ xmlnode_set_namespace(transport, "urn:xmpp:tmp:jingle:transports:ice-udp");
+ candidate = jabber_jingle_session_create_candidate_info(
+ purple_media_get_local_candidate(sess->media),
+ purple_media_get_remote_candidate(sess->media));
+ xmlnode_insert_child(transport, candidate);
+
return jingle;
}
-static guint
-jabber_jingle_get_priority(guint type, guint network)
-{
- switch (type) {
- case FARSIGHT_CANDIDATE_TYPE_LOCAL:
- return network == 0 ? 4096 : network == 1 ? 2048 : 1024;
- break;
- case FARSIGHT_CANDIDATE_TYPE_DERIVED:
- return 126;
- break;
- case FARSIGHT_CANDIDATE_TYPE_RELAY:
- return 100;
- break;
- default:
- return 0; /* unknown type, should not happen */
- }
-}
xmlnode *
-jabber_jingle_session_create_transport_info(const JingleSession *sess,
- gchar *candidate_id)
+jabber_jingle_session_create_transport_info(const JingleSession *sess)
{
xmlnode *jingle =
jabber_jingle_session_create_jingle_element(sess, "transport-info");
xmlnode *content = NULL;
xmlnode *transport = NULL;
- GList *candidates =
- farsight_stream_get_native_candidate(
- jabber_jingle_session_get_stream(sess), candidate_id);
-
+ GList *candidates = purple_media_get_local_audio_candidates(sess->media);
+
content = xmlnode_new_child(jingle, "content");
xmlnode_set_attrib(content, "creator", "initiator");
xmlnode_set_attrib(content, "name", "audio-content");
xmlnode_set_attrib(content, "profile", "RTP/AVP");
transport = xmlnode_new_child(content, "transport");
- xmlnode_set_namespace(transport, "urn:xmpp:tmp:jingle:transports:ice-tcp");
+ xmlnode_set_namespace(transport, "urn:xmpp:tmp:jingle:transports:ice-udp");
/* get transport candidate */
for (; candidates ; candidates = candidates->next) {
- FarsightTransportInfo *transport_info =
- (FarsightTransportInfo *) candidates->data;
- char port[8];
- char prio[8];
- char component[8];
- xmlnode *candidate = NULL;
-
- if (!strcmp(transport_info->ip, "127.0.0.1")) {
+ FsCandidate *c = (FsCandidate *) candidates->data;
+
+ if (!strcmp(c->ip, "127.0.0.1")) {
continue;
}
-
- candidate = xmlnode_new_child(transport, "candidate");
-
- g_snprintf(port, sizeof(port), "%d", transport_info->port);
- g_snprintf(prio, sizeof(prio), "%d",
- jabber_jingle_get_priority(transport_info->type, 0));
- g_snprintf(component, sizeof(component), "%d", transport_info->component);
-
- xmlnode_set_attrib(candidate, "component", component);
- xmlnode_set_attrib(candidate, "foundation", "1"); /* what about this? */
- xmlnode_set_attrib(candidate, "generation", "0"); /* ? */
- xmlnode_set_attrib(candidate, "ip", transport_info->ip);
- xmlnode_set_attrib(candidate, "network", "0"); /* ? */
- xmlnode_set_attrib(candidate, "port", port);
- xmlnode_set_attrib(candidate, "priority", prio); /* Is this correct? */
- xmlnode_set_attrib(candidate, "protocol",
- transport_info->proto == FARSIGHT_NETWORK_PROTOCOL_UDP ?
- "udp" : "tcp");
- if (transport_info->username)
- xmlnode_set_attrib(candidate, "ufrag", transport_info->username);
- if (transport_info->password)
- xmlnode_set_attrib(candidate, "pwd", transport_info->password);
-
- xmlnode_set_attrib(candidate, "type",
- transport_info->type == FARSIGHT_CANDIDATE_TYPE_LOCAL ?
- "host" :
- transport_info->type == FARSIGHT_CANDIDATE_TYPE_DERIVED ?
- "prflx" :
- transport_info->type == FARSIGHT_CANDIDATE_TYPE_RELAY ?
- "relay" : NULL);
-
+
+ xmlnode_insert_child(transport,
+ jabber_jingle_session_create_candidate_info(c, NULL));
}
- farsight_transport_list_destroy(candidates);
+ fs_candidate_list_destroy(candidates);
return jingle;
}
xmlnode *
jabber_jingle_session_create_content_replace(const JingleSession *sess,
- gchar *native_candidate_id,
- gchar *remote_candidate_id)
+ FsCandidate *native_candidate,
+ FsCandidate *remote_candidate)
{
xmlnode *jingle =
jabber_jingle_session_create_jingle_element(sess, "content-replace");
xmlnode *content = NULL;
xmlnode *transport = NULL;
- xmlnode *candidate = NULL;
- xmlnode *description = NULL;
- xmlnode *payload_type = NULL;
- char local_port[8];
- char remote_port[8];
- char prio[8];
- char component[8];
-
+
purple_debug_info("jingle", "creating content-modify for native candidate %s " \
- ", remote candidate %s\n", native_candidate_id,
- remote_candidate_id);
-
- /* It seems the ID's we get from the Farsight callback is phony... */
- /*
- GList *native_candidates =
- farsight_stream_get_native_candidate(jabber_jingle_session_get_stream(sess),
- native_candidate_id);
- purple_debug_info("jingle", "found %d native candidates with id %s\n",
- g_list_length(native_candidates), native_candidate_id);
- GList *remote_candidates =
- jabber_jingle_session_get_remote_candidate(sess, remote_candidate_id);
- */
-
- /* we assume lists have length == 1, I think they must... */
- /*
- FarsightTransportInfo *native =
- (FarsightTransportInfo *) native_candidates->data;
- FarsightTransportInfo *remote =
- (FarsightTransportInfo *) remote_candidates->data;
- */
-
+ ", remote candidate %s\n", native_candidate->candidate_id,
+ remote_candidate->candidate_id);
+
content = xmlnode_new_child(jingle, "content");
xmlnode_set_attrib(content, "creator", "initiator");
xmlnode_set_attrib(content, "name", "audio-content");
xmlnode_set_attrib(content, "profile", "RTP/AVP");
- description = xmlnode_new_child(content, "description");
- xmlnode_set_namespace(description, "urn:xmpp:tmp:jingle:apps:audio-rtp");
-
- payload_type = xmlnode_new_child(description, "payload-type");
/* get top codec from codec_intersection to put here... */
/* later on this should probably handle changing codec */
-
- /* Skip creating the actual "content" element for now, since we don't
- get enough info in the Farsight callback */
-#if 0
+
+ xmlnode_insert_child(content, jabber_jingle_session_create_description(sess));
+
transport = xmlnode_new_child(content, "transport");
- xmlnode_set_namespace(transport, "urn:xmpp:tmp:jingle:transports:ice-tcp");
-
- candidate = xmlnode_new_child(transport, "candidate");
-
- g_snprintf(local_port, sizeof(local_port), "%d", native->port);
- g_snprintf(remote_port, sizeof(remote_port), "%d", remote->port);
- g_snprintf(prio, sizeof(prio), "%d",
- jabber_jingle_get_priority(native->type, 0));
- g_snprintf(component, sizeof(component), "%d", native->component);
+ xmlnode_set_namespace(transport, "urn:xmpp:tmp:jingle:transports:ice-udp");
+ xmlnode_insert_child(transport,
+ jabber_jingle_session_create_candidate_info(native_candidate,
+ remote_candidate));
- xmlnode_set_attrib(candidate, "component", component);
- xmlnode_set_attrib(candidate, "foundation", "1"); /* what about this? */
- xmlnode_set_attrib(candidate, "generation", "0"); /* ? */
- xmlnode_set_attrib(candidate, "ip", native->ip);
- xmlnode_set_attrib(candidate, "network", "1"); /* ? */
- xmlnode_set_attrib(candidate, "port", local_port);
- xmlnode_set_attrib(candidate, "priority", prio); /* Is this correct? */
- xmlnode_set_attrib(candidate, "protocol",
- native->proto == FARSIGHT_NETWORK_PROTOCOL_UDP ?
- "udp" : "tcp");
- if (native->username)
- xmlnode_set_attrib(candidate, "ufrag", native->username);
- if (native->password)
- xmlnode_set_attrib(candidate, "pwd", native->password);
-
- xmlnode_set_attrib(candidate, "type",
- native->type == FARSIGHT_CANDIDATE_TYPE_LOCAL ?
- "host" :
- native->type == FARSIGHT_CANDIDATE_TYPE_DERIVED ?
- "prflx" :
- native->type == FARSIGHT_CANDIDATE_TYPE_RELAY ?
- "relay" : NULL);
- /* relay */
- if (native->type == FARSIGHT_CANDIDATE_TYPE_RELAY) {
- /* set rel-addr and rel-port? How? */
- }
-
- xmlnode_set_attrib(candidate, "rem-addr", remote->ip);
- xmlnode_set_attrib(candidate, "rem-port", remote_port);
-
- farsight_transport_list_destroy(native_candidates);
- farsight_transport_list_destroy(remote_candidates);
-
-#endif /* 0 */
-
purple_debug_info("jingle", "End create content modify\n");
return jingle;
@@ -556,24 +497,9 @@ jabber_jingle_session_create_content_acc
xmlnode_set_attrib(content, "name", "audio-content");
xmlnode_set_attrib(content, "profile", "RTP/AVP");
- xmlnode_insert_child(jingle, description);
+ xmlnode_insert_child(content, description);
return jingle;
}
-void
-jabber_jingle_session_set_remote_codecs(JingleSession *sess, GList *codecs)
-{
- if (sess->remote_codecs) {
- farsight_codec_list_destroy(sess->remote_codecs);
- }
- sess->remote_codecs = codecs;
-}
-
-GList *
-jabber_jingle_session_get_remote_codecs(const JingleSession *sess)
-{
- return sess->remote_codecs;
-}
-
#endif /* USE_FARSIGHT */
============================================================
--- libpurple/protocols/jabber/jingle.h 4b430554efe6404e70afb479525110880946afeb
+++ libpurple/protocols/jabber/jingle.h 00b86acf0c892457226781f37d217c49463f19a5
@@ -26,20 +26,16 @@
#ifdef USE_FARSIGHT
-#include <farsight/farsight.h>
-
G_BEGIN_DECLS
typedef struct {
char *id;
JabberStream *js;
- FarsightStream *stream;
PurpleMedia *media;
char *remote_jid;
char *initiator;
gboolean is_initiator;
- GList *remote_candidates;
- GList *remote_codecs;
+ gboolean session_started;
} JingleSession;
JingleSession *jabber_jingle_session_create(JabberStream *js);
@@ -52,10 +48,9 @@ JingleSession *jabber_jingle_session_fin
void jabber_jingle_session_destroy(JingleSession *sess);
JingleSession *jabber_jingle_session_find_by_id(const char *id);
+GList *jabber_jingle_session_find_by_js(JabberStream *js);
+JingleSession *jabber_jingle_session_find_by_jid(JabberStream *js, const char *jid);
-FarsightStream *jabber_jingle_session_get_stream(const JingleSession *sess);
-void jabber_jingle_session_set_stream(JingleSession *sess, FarsightStream *stream);
-
PurpleMedia *jabber_jingle_session_get_media(const JingleSession *sess);
void jabber_jingle_session_set_media(JingleSession *sess, PurpleMedia *media);
@@ -70,20 +65,16 @@ void jabber_jingle_session_set_initiator
void jabber_jingle_session_set_initiator(JingleSession *sess,
const char *initiator);
-void jabber_jingle_session_add_remote_candidate(JingleSession *sess,
- const GList *candidate);
-
xmlnode *jabber_jingle_session_create_terminate(const JingleSession *sess,
const char *reasoncode,
const char *reasontext);
-
xmlnode *jabber_jingle_session_create_session_accept(const JingleSession *sess);
-xmlnode *jabber_jingle_session_create_transport_info(const JingleSession *sess,
- gchar *candidate_id);
+xmlnode *jabber_jingle_session_create_transport_info(const JingleSession *sess);
xmlnode *jabber_jingle_session_create_content_replace(const JingleSession *sess,
- gchar *native_candidate_id,
- gchar *remote_candidate_id);
+ FsCandidate *native_candidate,
+ FsCandidate *remote_candidate);
xmlnode *jabber_jingle_session_create_content_accept(const JingleSession *sess);
+xmlnode *jabber_jingle_session_create_description(const JingleSession *sess);
/**
* Gets a list of Farsight codecs from a Jingle <description> tag
@@ -95,10 +86,6 @@ GList *jabber_jingle_get_candidates(cons
GList *jabber_jingle_get_candidates(const xmlnode *transport);
-void jabber_jingle_session_set_remote_codecs(JingleSession *sess,
- GList *codecs);
-GList *jabber_jingle_session_get_remote_codecs(const JingleSession *sess);
-
G_END_DECLS
#endif /* USE_FARSIGHT */
============================================================
--- pidgin/gtkmedia.c 366ef2bdb32c73b6c1bb1dcc8d604a70249a8caa
+++ pidgin/gtkmedia.c d39541eb18c2954feb5cc10709484a6e16893954
@@ -32,8 +32,6 @@
#ifdef USE_FARSIGHT
-#include <farsight/farsight.h>
-
typedef enum
{
/* Waiting for response */
@@ -181,37 +179,18 @@ pidgin_media_init (PidginMedia *media)
gtk_widget_show_all(media->priv->reject);
}
-static void
-pidgin_media_finalize (GObject *media)
-{
- PidginMedia *gtkmedia = PIDGIN_MEDIA(media);
- if (gtkmedia->priv->media)
- g_object_unref(gtkmedia->priv->media);
- if (gtkmedia->priv->send_level)
- gst_object_unref(gtkmedia->priv->send_level);
- if (gtkmedia->priv->recv_level)
- gst_object_unref(gtkmedia->priv->recv_level);
-}
-
-static void
-pidgin_media_emit_message(PidginMedia *gtkmedia, const char *msg)
-{
- g_signal_emit(gtkmedia, pidgin_media_signals[MESSAGE], 0, msg);
-}
-
static gboolean
level_message_cb(GstBus *bus, GstMessage *message, PidginMedia *gtkmedia)
{
const GstStructure *s;
const gchar *name;
- int channels;
- gdouble rms_db, peak_db, decay_db;
- gdouble rms;
+ gdouble rms_db;
+ gdouble percent;
const GValue *list;
const GValue *value;
- GstElement *src = GST_ELEMENT(message);
+ GstElement *src = GST_ELEMENT(GST_MESSAGE_SRC(message));
if (message->type != GST_MESSAGE_ELEMENT)
return TRUE;
@@ -228,15 +207,51 @@ level_message_cb(GstBus *bus, GstMessage
value = gst_value_list_get_value(list, 0);
rms_db = g_value_get_double(value);
+ percent = pow(10, rms_db / 20) * 5;
+
+ if(percent > 1.0)
+ percent = 1.0;
+
if (!strcmp(gst_element_get_name(src), "sendlevel"))
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(gtkmedia->priv->send_progress), pow(10, rms_db / 20) * 5);
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(gtkmedia->priv->send_progress), percent);
else
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(gtkmedia->priv->recv_progress), pow(10, rms_db / 20) * 5);
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(gtkmedia->priv->recv_progress), percent);
return TRUE;
}
+
static void
+pidgin_media_disconnect_levels(PurpleMedia *media, PidginMedia *gtkmedia)
+{
+ GstElement *element = purple_media_get_audio_pipeline(media);
+ gulong handler_id = g_signal_handler_find(G_OBJECT(gst_pipeline_get_bus(GST_PIPELINE(element))),
+ G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0,
+ NULL, G_CALLBACK(level_message_cb), gtkmedia);
+ g_signal_handler_disconnect(G_OBJECT(gst_pipeline_get_bus(GST_PIPELINE(element))), handler_id);
+}
+
+static void
+pidgin_media_finalize (GObject *media)
+{
+ PidginMedia *gtkmedia = PIDGIN_MEDIA(media);
+ if (gtkmedia->priv->media) {
+ pidgin_media_disconnect_levels(gtkmedia->priv->media, gtkmedia);
+ g_object_unref(gtkmedia->priv->media);
+ }
+ if (gtkmedia->priv->send_level)
+ gst_object_unref(gtkmedia->priv->send_level);
+ if (gtkmedia->priv->recv_level)
+ gst_object_unref(gtkmedia->priv->recv_level);
+}
+
+static void
+pidgin_media_emit_message(PidginMedia *gtkmedia, const char *msg)
+{
+ g_signal_emit(gtkmedia, pidgin_media_signals[MESSAGE], 0, msg);
+}
+
+static void
pidgin_media_ready_cb(PurpleMedia *media, PidginMedia *gtkmedia)
{
GstElement *element = purple_media_get_audio_pipeline(media);
============================================================
--- pidgin/gtkmedia.h 3e50ecb202f87961bb423d5d9bafc9aac5e96d5d
+++ pidgin/gtkmedia.h 98008273e4638ee6d218c317f6cbc5f07e277112
@@ -28,7 +28,6 @@
#ifdef USE_FARSIGHT
-#include <farsight/farsight.h>
#include <gtk/gtk.h>
#include <glib-object.h>
More information about the Commits
mailing list