# HG changeset patch # User Sadrul Habib Chowdhury # Date 1202327081 0 # Node ID f5bcb58bdf561a38330abd4a6043603b169d8fbc # Parent 762174f388071ecee0a5078e801b104117862a6a# Parent def0d893e7377dba05778be8198ffee698966834 propagate from branch 'im.pidgin.pidgin' (head 16d99d9757384d801e4f13d991cb769a71f9c190) to branch 'im.pidgin.pidgin.vv' (head 6fc5d53de8bd73364b370627020563c614fe6e0a) diff -r 762174f38807 -r f5bcb58bdf56 configure.ac --- a/configure.ac Wed Feb 06 15:50:41 2008 +0000 +++ b/configure.ac Wed Feb 06 19:44:41 2008 +0000 @@ -673,6 +673,23 @@ fi dnl ####################################################################### +dnl # Check for Farsight +dnl ####################################################################### +AC_ARG_ENABLE(farsight, + [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], [ + AC_DEFINE(USE_FARSIGHT, 1, [Use Farsight for voice and video]) + AC_SUBST(FARSIGHT_CFLAGS) + AC_SUBST(FARSIGHT_LIBS) + ], [ + AC_MSG_RESULT(no) + enable_farsight="no" + ]) +fi + +dnl ####################################################################### dnl # Check for Meanwhile headers (for Sametime) dnl ####################################################################### PKG_CHECK_MODULES(MEANWHILE, [meanwhile >= 1.0.0 meanwhile < 2.0.0], [ @@ -2274,6 +2291,7 @@ echo Protocols to link statically.. : $STATIC_PRPLS echo echo Build with GStreamer support.. : $enable_gst +echo Build with voice and video.... : $enable_farsight echo Build with D-Bus support...... : $enable_dbus if test "x$enable_dbus" = "xyes" ; then eval eval echo D-Bus services directory...... : $DBUS_SERVICES_DIR diff -r 762174f38807 -r f5bcb58bdf56 finch/Makefile.am --- a/finch/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -69,6 +69,7 @@ $(INTLLIBS) \ $(GLIB_LIBS) \ $(LIBXML_LIBS) \ + $(FARSIGHT_LIBS) \ $(GNT_LIBS) \ $(GSTREAMER_LIBS) \ ./libgnt/libgnt.la \ @@ -88,5 +89,6 @@ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) \ $(LIBXML_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(GSTREAMER_CFLAGS) \ $(GNT_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 finch/gntaccount.c --- a/finch/gntaccount.c Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/gntaccount.c Wed Feb 06 19:44:41 2008 +0000 @@ -23,6 +23,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include +#include +#include +#include +#include +#include + #include #include #include @@ -37,13 +44,6 @@ #include "finch.h" -#include -#include -#include -#include -#include -#include - #include "gntaccount.h" #include "gntblist.h" diff -r 762174f38807 -r f5bcb58bdf56 finch/gntdebug.c --- a/finch/gntdebug.c Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/gntdebug.c Wed Feb 06 19:44:41 2008 +0000 @@ -23,6 +23,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include "util.h" + #include #include #include @@ -36,7 +38,6 @@ #include "gntdebug.h" #include "finch.h" #include "notify.h" -#include "util.h" #include #include diff -r 762174f38807 -r f5bcb58bdf56 finch/gntft.c --- a/finch/gntft.c Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/gntft.c Wed Feb 06 19:44:41 2008 +0000 @@ -25,6 +25,12 @@ */ #include "finch.h" +#include "debug.h" +#include "notify.h" +#include "ft.h" +#include "prpl.h" +#include "util.h" + #include #include #include @@ -32,12 +38,6 @@ #include #include -#include "debug.h" -#include "notify.h" -#include "ft.h" -#include "prpl.h" -#include "util.h" - #include "gntft.h" #include "prefs.h" diff -r 762174f38807 -r f5bcb58bdf56 finch/gntnotify.c --- a/finch/gntnotify.c Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/gntnotify.c Wed Feb 06 19:44:41 2008 +0000 @@ -23,6 +23,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include + #include #include #include @@ -32,7 +34,6 @@ #include "finch.h" -#include #include "gntnotify.h" diff -r 762174f38807 -r f5bcb58bdf56 finch/gntplugin.c --- a/finch/gntplugin.c Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/gntplugin.c Wed Feb 06 19:44:41 2008 +0000 @@ -23,6 +23,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include "notify.h" +#include "request.h" + #include #include #include @@ -34,8 +37,6 @@ #include "finch.h" #include "debug.h" -#include "notify.h" -#include "request.h" #include "gntplugin.h" #include "gntrequest.h" diff -r 762174f38807 -r f5bcb58bdf56 finch/gntpounce.c --- a/finch/gntpounce.c Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/gntpounce.c Wed Feb 06 19:44:41 2008 +0000 @@ -24,6 +24,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * */ +#include "internal.h" +#include "account.h" +#include "conversation.h" +#include "debug.h" +#include "notify.h" +#include "prpl.h" +#include "request.h" +#include "server.h" +#include "util.h" + #include #include #include @@ -37,15 +47,6 @@ #include "finch.h" -#include "account.h" -#include "conversation.h" -#include "debug.h" -#include "notify.h" -#include "prpl.h" -#include "request.h" -#include "server.h" -#include "util.h" - #include "gntpounce.h" diff -r 762174f38807 -r f5bcb58bdf56 finch/gntrequest.c --- a/finch/gntrequest.c Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/gntrequest.c Wed Feb 06 19:44:41 2008 +0000 @@ -23,6 +23,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +#include "util.h" + #include #include #include @@ -37,7 +40,6 @@ #include "finch.h" #include "gntrequest.h" #include "debug.h" -#include "util.h" typedef struct { diff -r 762174f38807 -r f5bcb58bdf56 finch/gntstatus.c --- a/finch/gntstatus.c Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/gntstatus.c Wed Feb 06 19:44:41 2008 +0000 @@ -23,6 +23,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +#include +#include + #include #include #include @@ -35,9 +39,6 @@ #include "finch.h" -#include -#include - #include "gntstatus.h" static struct diff -r 762174f38807 -r f5bcb58bdf56 finch/gntui.c --- a/finch/gntui.c Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/gntui.c Wed Feb 06 19:44:41 2008 +0000 @@ -19,9 +19,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include #include "finch.h" -#include "gntui.h" #include "gntaccount.h" #include "gntblist.h" @@ -40,7 +40,7 @@ #include "gntstatus.h" #include "gntsound.h" -#include +#include "gntui.h" void gnt_ui_init() { diff -r 762174f38807 -r f5bcb58bdf56 finch/libgnt/Makefile.am --- a/finch/libgnt/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/libgnt/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -89,6 +89,7 @@ AM_CPPFLAGS = \ $(GLIB_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(GNT_CFLAGS) \ $(DEBUG_CFLAGS) \ $(LIBXML_CFLAGS) \ diff -r 762174f38807 -r f5bcb58bdf56 finch/libgnt/wms/Makefile.am --- a/finch/libgnt/wms/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/libgnt/wms/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -34,5 +34,6 @@ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ $(GNT_CFLAGS) \ - $(PLUGIN_CFLAGS) + $(PLUGIN_CFLAGS) \ + $(FARSIGHT_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 finch/libgnt/wms/s.c --- a/finch/libgnt/wms/s.c Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/libgnt/wms/s.c Wed Feb 06 19:44:41 2008 +0000 @@ -2,6 +2,7 @@ #include #include "internal.h" +#include "blist.h" #include "gnt.h" #include "gntbox.h" @@ -11,7 +12,6 @@ #include "gntwindow.h" #include "gntlabel.h" -#include "blist.h" #define TYPE_S (s_get_gtype()) diff -r 762174f38807 -r f5bcb58bdf56 finch/plugins/Makefile.am --- a/finch/plugins/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/finch/plugins/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -42,6 +42,7 @@ -I$(top_srcdir)/finch \ -I$(top_srcdir)/finch/libgnt \ $(DEBUG_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(GLIB_CFLAGS) \ $(GNT_CFLAGS) \ $(PLUGIN_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/Makefile.am --- a/libpurple/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -51,6 +51,8 @@ idle.c \ imgstore.c \ log.c \ + media.c \ + mediamanager.c \ mime.c \ nat-pmp.c \ network.c \ @@ -103,6 +105,8 @@ idle.h \ imgstore.h \ log.h \ + media.h \ + mediamanager.h \ mime.h \ nat-pmp.h \ network.h \ @@ -246,6 +250,7 @@ $(LIBXML_LIBS) \ $(LIBNM_LIBS) \ $(INTLLIBS) \ + $(FARSIGHT_LIBS) \ -lm AM_CPPFLAGS = \ @@ -258,4 +263,5 @@ $(DEBUG_CFLAGS) \ $(DBUS_CFLAGS) \ $(LIBXML_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(LIBNM_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/example/Makefile.am --- a/libpurple/example/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/example/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -8,6 +8,7 @@ $(INTLLIBS) \ $(GLIB_LIBS) \ $(LIBXML_LIBS) \ + $(FARSIGHT_LIBS) \ $(top_builddir)/libpurple/libpurple.la AM_CPPFLAGS = \ @@ -23,4 +24,5 @@ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(LIBXML_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/media.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/media.c Wed Feb 06 19:44:41 2008 +0000 @@ -0,0 +1,458 @@ +/** + * @file media.c Media API + * @ingroup core + * + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "internal.h" + +#include "connection.h" +#include "media.h" + +#ifdef USE_FARSIGHT + +#include + +struct _PurpleMediaPrivate +{ + FarsightSession *farsight_session; + + char *name; + PurpleConnection *connection; + GstElement *audio_src; + GstElement *audio_sink; + GstElement *video_src; + GstElement *video_sink; + + FarsightStream *audio_stream; + FarsightStream *video_stream; +}; + +#define PURPLE_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA, PurpleMediaPrivate)) + +static void purple_media_class_init (PurpleMediaClass *klass); +static void purple_media_init (PurpleMedia *media); +static void purple_media_finalize (GObject *object); +static void purple_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static void purple_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); + +static GObjectClass *parent_class = NULL; + + + +enum { + READY, + ACCEPTED, + HANGUP, + REJECT, + GOT_HANGUP, + LAST_SIGNAL +}; +static guint purple_media_signals[LAST_SIGNAL] = {0}; + +enum { + PROP_0, + PROP_FARSIGHT_SESSION, + PROP_NAME, + PROP_CONNECTION, + PROP_AUDIO_SRC, + PROP_AUDIO_SINK, + PROP_VIDEO_SRC, + PROP_VIDEO_SINK, + PROP_VIDEO_STREAM, + PROP_AUDIO_STREAM +}; + +GType +purple_media_get_type() +{ + static GType type = 0; + + if (type == 0) { + static const GTypeInfo info = { + sizeof(PurpleMediaClass), + NULL, + NULL, + (GClassInitFunc) purple_media_class_init, + NULL, + NULL, + sizeof(PurpleMedia), + 0, + (GInstanceInitFunc) purple_media_init, + NULL + }; + type = g_type_register_static(G_TYPE_OBJECT, "PurpleMedia", &info, 0); + } + return type; +} + + +static void +purple_media_class_init (PurpleMediaClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass*)klass; + parent_class = g_type_class_peek_parent(klass); + + gobject_class->finalize = purple_media_finalize; + 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_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_NAME, + g_param_spec_string("screenname", + "Screenname", + "The screenname of the remote user", + NULL, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_CONNECTION, + g_param_spec_pointer("connection", + "Connection", + "The PurpleConnection associated with this session", + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_AUDIO_SRC, + g_param_spec_object("audio-src", + "Audio source", + "The GstElement used to source audio", + GST_TYPE_ELEMENT, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_AUDIO_SINK, + g_param_spec_object("audio-sink", + "Audio sink", + "The GstElement used to sink audio", + GST_TYPE_ELEMENT, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_VIDEO_SRC, + g_param_spec_object("video-src", + "Video source", + "The GstElement used to source video", + GST_TYPE_ELEMENT, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_VIDEO_SINK, + g_param_spec_object("video-sink", + "Audio source", + "The GstElement used to sink video", + GST_TYPE_ELEMENT, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_VIDEO_STREAM, + g_param_spec_object("video-stream", + "Video stream", + "The FarsightStream used for video", + FARSIGHT_TYPE_STREAM, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_AUDIO_STREAM, + g_param_spec_object("audio-stream", + "Audio stream", + "The FarsightStream used for audio", + FARSIGHT_TYPE_STREAM, + G_PARAM_READWRITE)); + + purple_media_signals[READY] = g_signal_new("ready", G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + purple_media_signals[ACCEPTED] = g_signal_new("accepted", G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + purple_media_signals[HANGUP] = g_signal_new("hangup", G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + purple_media_signals[REJECT] = g_signal_new("reject", G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + purple_media_signals[GOT_HANGUP] = g_signal_new("got-hangup", G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_type_class_add_private(klass, sizeof(PurpleMediaPrivate)); +} + + +static void +purple_media_init (PurpleMedia *media) +{ + media->priv = PURPLE_MEDIA_GET_PRIVATE(media); + memset(media->priv, 0, sizeof(media->priv)); +} + +static void +purple_media_finalize (GObject *media) +{ + parent_class->finalize(media); +} + +static void +purple_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + PurpleMedia *media; + g_return_if_fail(PURPLE_IS_MEDIA(object)); + + 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); + break; + case PROP_NAME: + g_free(media->priv->name); + media->priv->name = g_value_dup_string(value); + break; + case PROP_CONNECTION: + media->priv->connection = g_value_get_pointer(value); + break; + case PROP_AUDIO_SRC: + if (media->priv->audio_src) + gst_object_unref(media->priv->audio_src); + media->priv->audio_src = g_value_get_object(value); + gst_object_ref(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); + break; + case PROP_VIDEO_SRC: + if (media->priv->video_src) + gst_object_unref(media->priv->video_src); + media->priv->video_src = g_value_get_object(value); + gst_object_ref(media->priv->video_src); + break; + case PROP_VIDEO_SINK: + if (media->priv->video_sink) + gst_object_unref(media->priv->video_sink); + 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); + 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); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +purple_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + PurpleMedia *media; + g_return_if_fail(PURPLE_IS_MEDIA(object)); + + media = PURPLE_MEDIA(object); + + switch (prop_id) { + case PROP_FARSIGHT_SESSION: + g_value_set_object(value, media->priv->farsight_session); + break; + case PROP_NAME: + g_value_set_string(value, media->priv->name); + break; + case PROP_CONNECTION: + g_value_set_pointer(value, media->priv->connection); + break; + case PROP_AUDIO_SRC: + g_value_set_object(value, media->priv->audio_src); + break; + case PROP_AUDIO_SINK: + g_value_set_object(value, media->priv->audio_sink); + break; + case PROP_VIDEO_SRC: + g_value_set_object(value, media->priv->video_src); + break; + 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); + break; + case PROP_AUDIO_STREAM: + g_value_set_object(value, media->priv->audio_stream); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} + +void +purple_media_get_elements(PurpleMedia *media, GstElement **audio_src, GstElement **audio_sink, + GstElement **video_src, GstElement **video_sink) +{ + if (audio_src) + g_object_get(G_OBJECT(media), "audio-src", *audio_src, NULL); + if (audio_sink) + g_object_get(G_OBJECT(media), "audio-sink", *audio_sink, NULL); + if (video_src) + g_object_get(G_OBJECT(media), "video-src", *video_src, NULL); + if (video_sink) + g_object_get(G_OBJECT(media), "video-sink", *video_sink, NULL); + +} + +void +purple_media_set_audio_src(PurpleMedia *media, GstElement *audio_src) +{ + g_object_set(G_OBJECT(media), "audio-src", audio_src, NULL); +} + +void +purple_media_set_audio_sink(PurpleMedia *media, GstElement *audio_sink) +{ + g_object_set(G_OBJECT(media), "audio-sink", audio_sink, NULL); +} + +void +purple_media_set_video_src(PurpleMedia *media, GstElement *video_src) +{ + g_object_set(G_OBJECT(media), "video-src", video_src, NULL); +} + +void +purple_media_set_video_sink(PurpleMedia *media, GstElement *video_sink) +{ + g_object_set(G_OBJECT(media), "video-sink", video_sink, NULL); +} + +GstElement * +purple_media_get_audio_src(PurpleMedia *media) +{ + GstElement *ret; + g_object_get(G_OBJECT(media), "audio-src", &ret, NULL); + return ret; +} + +GstElement * +purple_media_get_audio_sink(PurpleMedia *media) +{ + GstElement *ret; + g_object_get(G_OBJECT(media), "audio-sink", &ret, NULL); + return ret; +} + +GstElement * +purple_media_get_video_src(PurpleMedia *media) +{ + GstElement *ret; + g_object_get(G_OBJECT(media), "video-src", &ret, NULL); + return ret; +} + +GstElement * +purple_media_get_video_sink(PurpleMedia *media) +{ + GstElement *ret; + g_object_get(G_OBJECT(media), "video-sink", &ret, NULL); + return ret; +} + +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); +} + +PurpleConnection * +purple_media_get_connection(PurpleMedia *media) +{ + PurpleConnection *gc; + g_object_get(G_OBJECT(media), "connection", &gc, NULL); + return gc; +} + +const char * +purple_media_get_screenname(PurpleMedia *media) +{ + const char *ret; + g_object_get(G_OBJECT(media), "screenname", &ret, NULL); + return ret; +} + +void +purple_media_ready(PurpleMedia *media) +{ + g_signal_emit(media, purple_media_signals[READY], 0); +} + +void +purple_media_accept(PurpleMedia *media) +{ + g_signal_emit(media, purple_media_signals[ACCEPTED], 0); +} + +void +purple_media_hangup(PurpleMedia *media) +{ + g_signal_emit(media, purple_media_signals[HANGUP], 0); +} + +void +purple_media_reject(PurpleMedia *media) +{ + g_signal_emit(media, purple_media_signals[REJECT], 0); +} + +void +purple_media_got_hangup(PurpleMedia *media) +{ + g_signal_emit(media, purple_media_signals[GOT_HANGUP], 0); +} + +#endif /* USE_FARSIGHT */ diff -r 762174f38807 -r f5bcb58bdf56 libpurple/media.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/media.h Wed Feb 06 19:44:41 2008 +0000 @@ -0,0 +1,97 @@ +/** + * @file media.h Media API + * @ingroup core + * + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MEDIA_H_ +#define __MEDIA_H_ + +#ifdef USE_FARSIGHT + +#include +#include +#include + +#include "connection.h" + +G_BEGIN_DECLS + +#define PURPLE_TYPE_MEDIA (purple_media_get_type()) +#define PURPLE_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MEDIA, PurpleMedia)) +#define PURPLE_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MEDIA, PurpleMediaClass)) +#define PURPLE_IS_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_MEDIA)) +#define PURPLE_IS_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_MEDIA)) +#define PURPLE_MEDIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MEDIA, PurpleMediaClass)) + +typedef struct _PurpleMedia PurpleMedia; +typedef struct _PurpleMediaClass PurpleMediaClass; +typedef struct _PurpleMediaPrivate PurpleMediaPrivate; + +typedef enum { + PURPLE_MEDIA_RECV_AUDIO = 1 << 0, + PURPLE_MEDIA_SEND_AUDIO = 1 << 1, + PURPLE_MEDIA_RECV_VIDEO = 1 << 2, + PURPLE_MEDIA_SEND_VIDEO = 1 << 3, +} PurpleMediaStreamType; + +struct _PurpleMediaClass +{ + GObjectClass parent_class; +}; + +struct _PurpleMedia +{ + GObject parent; + PurpleMediaPrivate *priv; +}; + +GType purple_media_get_type(void); + +void purple_media_get_elements(PurpleMedia *media, GstElement **audio_src, GstElement **audio_sink, + GstElement **video_src, GstElement **video_sink); + +void purple_media_set_audio_src(PurpleMedia *media, GstElement *video_src); +void purple_media_set_audio_sink(PurpleMedia *media, GstElement *video_src); +void purple_media_set_video_src(PurpleMedia *media, GstElement *video_src); +void purple_media_set_video_sink(PurpleMedia *media, GstElement *video_src); + +GstElement *purple_media_get_audio_src(PurpleMedia *media); +GstElement *purple_media_get_audio_sink(PurpleMedia *media); +GstElement *purple_media_get_video_src(PurpleMedia *media); +GstElement *purple_media_get_video_sink(PurpleMedia *media); + +GstElement *purple_media_get_audio_pipeline(PurpleMedia *media); + +PurpleConnection *purple_media_get_connection(PurpleMedia *media); +const char *purple_media_get_screenname(PurpleMedia *media); +void purple_media_ready(PurpleMedia *media); +void purple_media_accept(PurpleMedia *media); +void purple_media_reject(PurpleMedia *media); +void purple_media_hangup(PurpleMedia *media); +void purple_media_got_hangup(PurpleMedia *media); +G_END_DECLS + +#endif /* USE_FARSIGHT */ + + +#endif /* __MEDIA_H_ */ diff -r 762174f38807 -r f5bcb58bdf56 libpurple/mediamanager.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/mediamanager.c Wed Feb 06 19:44:41 2008 +0000 @@ -0,0 +1,147 @@ +/** + * @file mediamanager.c Media Manager API + * @ingroup core + * + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "internal.h" + +#include "connection.h" +#include "mediamanager.h" +#include "media.h" + +#ifdef USE_FARSIGHT + +#include + +struct _PurpleMediaManagerPrivate +{ + GList *medias; +}; + +#define PURPLE_MEDIA_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManagerPrivate)) + +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); + +static GObjectClass *parent_class = NULL; + + + +enum { + INIT_MEDIA, + LAST_SIGNAL +}; +static guint purple_media_manager_signals[LAST_SIGNAL] = {0}; + +enum { + PROP_0, + PROP_FARSIGHT_SESSION, + PROP_NAME, + PROP_CONNECTION, + PROP_MIC_ELEMENT, + PROP_SPEAKER_ELEMENT, +}; + +GType +purple_media_manager_get_type() +{ + static GType type = 0; + + if (type == 0) { + static const GTypeInfo info = { + sizeof(PurpleMediaManagerClass), + NULL, + NULL, + (GClassInitFunc) purple_media_manager_class_init, + NULL, + NULL, + sizeof(PurpleMediaManager), + 0, + (GInstanceInitFunc) purple_media_manager_init, + NULL + }; + type = g_type_register_static(G_TYPE_OBJECT, "PurpleMediaManager", &info, 0); + } + return type; +} + + +static void +purple_media_manager_class_init (PurpleMediaManagerClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass*)klass; + parent_class = g_type_class_peek_parent(klass); + + gobject_class->finalize = purple_media_manager_finalize; + + purple_media_manager_signals[INIT_MEDIA] = g_signal_new ("init-media", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, PURPLE_TYPE_MEDIA); + g_type_class_add_private(klass, sizeof(PurpleMediaManagerPrivate)); +} + +static void +purple_media_manager_init (PurpleMediaManager *media) +{ + media->priv = PURPLE_MEDIA_MANAGER_GET_PRIVATE(media); + media->priv->medias = NULL; +} + +static void +purple_media_manager_finalize (GObject *media) +{ + parent_class->finalize(media); +} + +PurpleMediaManager * +purple_media_manager_get() +{ + static PurpleMediaManager *manager = NULL; + + if (manager == NULL) + manager = PURPLE_MEDIA_MANAGER(g_object_new(purple_media_manager_get_type(), NULL)); + return manager; +} + +PurpleMedia* +purple_media_manager_create_media(PurpleMediaManager *manager, + PurpleConnection *gc, + const char *screenname, + FarsightStream *audio_stream, + FarsightStream *video_stream) +{ + PurpleMedia *media = PURPLE_MEDIA(g_object_new(purple_media_get_type(), + "screenname", screenname, + "connection", gc, + "audio-stream", audio_stream, + "video-stream", video_stream, 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; +} + +#endif /* USE_FARSIGHT */ diff -r 762174f38807 -r f5bcb58bdf56 libpurple/mediamanager.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/mediamanager.h Wed Feb 06 19:44:41 2008 +0000 @@ -0,0 +1,76 @@ +/** + * @file mediamanager.h Media Manager API + * @ingroup core + * + * purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MEDIA_MANAGER_H_ +#define __MEDIA_MANAGER_H_ + +#ifdef USE_FARSIGHT + +#include +#include +#include + +#include "connection.h" +#include "media.h" + +G_BEGIN_DECLS + +#define PURPLE_TYPE_MEDIA_MANAGER (purple_media_manager_get_type()) +#define PURPLE_MEDIA_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManager)) +#define PURPLE_MEDIA_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManagerClass)) +#define PURPLE_IS_MEDIA_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_MEDIA_MANAGER)) +#define PURPLE_IS_MEDIA_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_MEDIA_MANAGER)) +#define PURPLE_MEDIA_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManagerClass)) + +typedef struct _PurpleMediaManager PurpleMediaManager; +typedef struct _PurpleMediaManagerClass PurpleMediaManagerClass; +typedef struct _PurpleMediaManagerPrivate PurpleMediaManagerPrivate; + +struct _PurpleMediaManagerClass +{ + GObjectClass parent_class; +}; + +struct _PurpleMediaManager +{ + GObject parent; + PurpleMediaManagerPrivate *priv; +}; + +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); + +G_END_DECLS + +#endif /* USE_FARSIGHT */ + + +#endif /* __MEDIA_MANAGER_H_ */ diff -r 762174f38807 -r f5bcb58bdf56 libpurple/plugins/Makefile.am --- a/libpurple/plugins/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/plugins/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -140,6 +140,7 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(DEBUG_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(GLIB_CFLAGS) \ $(PLUGIN_CFLAGS) \ $(DBUS_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/plugins/perl/Makefile.am --- a/libpurple/plugins/perl/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/plugins/perl/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -5,7 +5,7 @@ plugin_LTLIBRARIES = perl.la perl_la_LDFLAGS = -module -avoid-version -perl_la_LIBADD = $(GLIB_LIBS) $(PERL_LIBS) +perl_la_LIBADD = $(GLIB_LIBS) $(PERL_LIBS) $(FARSIGHT_LIBS) perl_la_SOURCES = \ perl.c \ perl-common.c \ @@ -159,4 +159,5 @@ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ $(PLUGIN_CFLAGS) \ - $(PERL_CFLAGS) + $(PERL_CFLAGS) \ + $(FARSIGHT_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/plugins/ssl/Makefile.am --- a/libpurple/plugins/ssl/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/plugins/ssl/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -31,6 +31,7 @@ -I$(top_builddir)/libpurple \ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(PLUGIN_CFLAGS) ssl_gnutls_la_CFLAGS = $(AM_CPPFLAGS) $(GNUTLS_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/plugins/tcl/Makefile.am --- a/libpurple/plugins/tcl/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/plugins/tcl/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -7,7 +7,7 @@ tcl_la_SOURCES = tcl.c tcl_glib.c tcl_glib.h tcl_cmds.c tcl_signals.c tcl_purple.h \ tcl_ref.c tcl_cmd.c -tcl_la_LIBADD = $(GLIB_LIBS) $(TCL_LIBS) $(TK_LIBS) +tcl_la_LIBADD = $(GLIB_LIBS) $(TCL_LIBS) $(TK_LIBS) $(FARSIGHT_LIBS) EXTRA_DIST = signal-test.tcl Makefile.mingw @@ -18,5 +18,6 @@ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ $(PLUGIN_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(TK_CFLAGS) \ $(TCL_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/bonjour/Makefile.am --- a/libpurple/protocols/bonjour/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/bonjour/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -51,5 +51,10 @@ $(GLIB_CFLAGS) \ $(DEBUG_CFLAGS) \ $(LIBXML_CFLAGS) \ - $(AVAHI_CFLAGS) + $(FARSIGHT_CFLAGS) +if MDNS_AVAHI + AM_CPPFLAGS += $(AVAHI_CFLAGS) +else +endif + diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/bonjour/bonjour.c --- a/libpurple/protocols/bonjour/bonjour.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/bonjour/bonjour.c Wed Feb 06 19:44:41 2008 +0000 @@ -482,12 +482,11 @@ NULL, /* whiteboard_prpl_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ - - /* padding */ - NULL, - NULL, - NULL, - NULL + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* get_attention_types */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; static PurplePluginInfo info = diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/gg/Makefile.am --- a/libpurple/protocols/gg/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/gg/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -75,5 +75,6 @@ -I$(top_builddir)/libpurple \ $(INTGG_CFLAGS) \ $(GLIB_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(DEBUG_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/gg/gg.c --- a/libpurple/protocols/gg/gg.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/gg/gg.c Wed Feb 06 19:44:41 2008 +0000 @@ -2147,12 +2147,11 @@ NULL, /* whiteboard_prpl_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ - - /* padding */ - NULL, - NULL, - NULL, - NULL + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* get_attention_types */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; /* }}} */ diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/irc/Makefile.am --- a/libpurple/protocols/irc/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/irc/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -32,4 +32,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(DEBUG_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/irc/irc.c --- a/libpurple/protocols/irc/irc.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/irc/irc.c Wed Feb 06 19:44:41 2008 +0000 @@ -900,12 +900,11 @@ NULL, /* whiteboard_prpl_ops */ irc_send_raw, /* send_raw */ NULL, /* roomlist_room_serialize */ - - /* padding */ - NULL, - NULL, - NULL, - NULL + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* get_attention_types */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; static gboolean load_plugin (PurplePlugin *plugin) { diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/jabber/Makefile.am --- a/libpurple/protocols/jabber/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/jabber/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -82,4 +82,5 @@ -I$(top_builddir)/libpurple \ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(LIBXML_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/jabber/disco.c Wed Feb 06 19:44:41 2008 +0000 @@ -142,6 +142,15 @@ SUPPORT_FEATURE(feat->namespace); } } + } else if (node && !strcmp(node, CAPS0115_NODE "#voice-v1")) { + SUPPORT_FEATURE("http://www.google.com/session"); + SUPPORT_FEATURE("http://www.google.com/transport/p2p"); + SUPPORT_FEATURE("http://www.google.com/transport/raw-udp"); + SUPPORT_FEATURE("http://www.google.com/session/phone"); + SUPPORT_FEATURE("http://www.xmpp.org/extensions/xep-0166.html"); + SUPPORT_FEATURE("http://www.xmpp.org/extensions/xep-0180.html"); + SUPPORT_FEATURE("http://www.xmpp.org/extensions/xep-0167.html"); + SUPPORT_FEATURE("http://www.xmpp.org/extensions/xep-0177.html"); } else { const char *ext = NULL; unsigned pos; diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/jabber/google.c --- a/libpurple/protocols/jabber/google.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/jabber/google.c Wed Feb 06 19:44:41 2008 +0000 @@ -18,8 +18,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include + #include "internal.h" #include "debug.h" +#include "mediamanager.h" #include "util.h" #include "privacy.h" @@ -29,6 +32,366 @@ #include "presence.h" #include "iq.h" +typedef struct { + char *id; + char *initiator; +} GoogleSessionId; + +typedef enum { + UNINIT, + SENT_INITIATE, + RECEIVED_INITIATE, + IN_PRORESS, + TERMINATED +} GoogleSessionState; + +typedef struct { + GoogleSessionId id; + GoogleSessionState state; + PurpleMedia *media; + FarsightStream *stream; + JabberStream *js; + char *remote_jid; +} GoogleSession; + +GHashTable *sessions = NULL; + +static guint +google_session_id_hash(gconstpointer key) +{ + GoogleSessionId *id = (GoogleSessionId*)key; + + guint id_hash = g_str_hash(id->id); + guint init_hash = g_str_hash(id->initiator); + + return 23 * id_hash + init_hash; +} + +static gboolean +google_session_id_equal(gconstpointer a, gconstpointer b) +{ + GoogleSessionId *c = (GoogleSessionId*)a; + GoogleSessionId *d = (GoogleSessionId*)b; + + return !strcmp(c->id, d->id) && !strcmp(c->initiator, d->initiator); +} + +static void +google_session_destroy(GoogleSession *session) +{ + g_hash_table_remove(sessions, &(session->id)); + g_free(session->id.id); + g_free(session->id.initiator); + g_free(session->remote_jid); + g_object_unref(session->media); + g_object_unref(session->stream); + g_free(session); +} + +static xmlnode * +google_session_create_xmlnode(GoogleSession *session, const char *type) +{ + xmlnode *node = xmlnode_new("session"); + xmlnode_set_namespace(node, "http://www.google.com/session"); + xmlnode_set_attrib(node, "id", session->id.id); + xmlnode_set_attrib(node, "initiator", session->id.initiator); + xmlnode_set_attrib(node, "type", type); + return node; +} + +static void +google_session_send_accept(GoogleSession *session) +{ + xmlnode *sess, *desc, *payload; + 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); + sess = google_session_create_xmlnode(session, "accept"); + xmlnode_insert_child(iq->node, sess); + desc = xmlnode_new_child(sess, "description"); + xmlnode_set_namespace(desc, "http://www.google.com/session/phone"); + + for (;codecs; codecs = codecs->next) { + FarsightCodec *codec = (FarsightCodec*)codecs->data; + char id[8], clockrate[10]; + payload = xmlnode_new_child(desc, "payload-type"); + g_snprintf(id, sizeof(id), "%d", codec->id); + g_snprintf(clockrate, sizeof(clockrate), "%d", codec->clock_rate); + xmlnode_set_attrib(payload, "name", codec->encoding_name); + xmlnode_set_attrib(payload, "id", id); + xmlnode_set_attrib(payload, "clockrate", clockrate); + } + + jabber_iq_send(iq); + farsight_stream_start(session->stream); +} + +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); + sess = google_session_create_xmlnode(session, "terminate"); + xmlnode_insert_child(iq->node, sess); + + jabber_iq_send(iq); + farsight_stream_stop(session->stream); + google_session_destroy(session); +} + +static void +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); + sess = google_session_create_xmlnode(session, "reject"); + 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) +{ + JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET); + GList *candidates = farsight_stream_get_native_candidate_list(stream); + FarsightTransportInfo *transport; + xmlnode *sess; + xmlnode *candidate; + sess = google_session_create_xmlnode(session, "candidates"); + xmlnode_insert_child(iq->node, sess); + xmlnode_set_attrib(iq->node, "to", session->remote_jid); + + for (;candidates;candidates = candidates->next) { + transport = (FarsightTransportInfo*)(candidates->data); + char port[8]; + char pref[8]; + + if (!strcmp(transport->ip, "127.0.0.1")) + continue; + + candidate = xmlnode_new("candidate"); + + g_snprintf(port, sizeof(port), "%d", transport->port); + g_snprintf(pref, sizeof(pref), "%f", transport->preference); + + xmlnode_set_attrib(candidate, "address", transport->ip); + xmlnode_set_attrib(candidate, "port", port); + xmlnode_set_attrib(candidate, "name", "rtp"); + 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, "generation", "0"); + xmlnode_set_attrib(candidate, "network", "0"); + xmlnode_insert_child(sess, candidate); + + } + jabber_iq_send(iq); +} + +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; + 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; + } + + 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); + + g_object_set(G_OBJECT(session->stream), "transmitter", "libjingle", NULL); + + desc_element = xmlnode_get_child(sess, "description"); + + for (codec_element = xmlnode_get_child(desc_element, "payload-type"); + codec_element; + codec_element = xmlnode_get_next_twin(codec_element)) { + encoding_name = xmlnode_get_attrib(codec_element, "name"); + 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); + 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); + + 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); + + + 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); + jabber_iq_send(result); +} + +static void +google_session_handle_candidates(JabberStream *js, GoogleSession *session, xmlnode *packet, xmlnode *sess) +{ + JabberIq *result; + GList *list = NULL; + xmlnode *cand; + static int name = 0; + char n[4]; + + for (cand = xmlnode_get_child(sess, "candidate"); cand; cand = xmlnode_get_next_twin(cand)) { + FarsightTransportInfo *info = g_new0(FarsightTransportInfo, 1); + 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"); + 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); + + 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); + jabber_iq_send(result); +} + +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); +} + +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); +} + +static void +google_session_parse_iq(JabberStream *js, GoogleSession *session, xmlnode *packet) +{ + xmlnode *sess = xmlnode_get_child(packet, "session"); + const char *type = xmlnode_get_attrib(sess, "type"); + + if (!strcmp(type, "initiate")) { + google_session_handle_initiate(js, session, packet, sess); + } else if (!strcmp(type, "accept")) { + } else if (!strcmp(type, "reject")) { + google_session_handle_reject(js, session, packet, sess); + } else if (!strcmp(type, "terminate")) { + google_session_handle_terminate(js, session, packet, sess); + } else if (!strcmp(type, "candidates")) { + google_session_handle_candidates(js, session, packet, sess); + } +} + +void +jabber_google_session_parse(JabberStream *js, xmlnode *packet) +{ + GoogleSession *session; + GoogleSessionId id; + JabberIq *result; + + xmlnode *session_node; + xmlnode *desc_node; + + if (strcmp(xmlnode_get_attrib(packet, "type"), "set")) + return; + + session_node = xmlnode_get_child(packet, "session"); + if (!session_node) + return; + + id.id = xmlnode_get_attrib(session_node, "id"); + if (!id.id) + return; + + id.initiator = xmlnode_get_attrib(session_node, "initiator"); + if (!id.initiator) + return; + + if (sessions == NULL) + sessions = g_hash_table_new(google_session_id_hash, google_session_id_equal); + session = (GoogleSession*)g_hash_table_lookup(sessions, &id); + + if (session) { + google_session_parse_iq(js, session, packet); + return; + } + + /* If the session doesn't exist, this has to be an initiate message */ + if (strcmp(xmlnode_get_attrib(session_node, "type"), "initiate")) + return; + desc_node = xmlnode_get_child(session_node, "description"); + if (!desc_node) + return; + session = g_new0(GoogleSession, 1); + session->id.id = g_strdup(id.id); + session->id.initiator = g_strdup(id.initiator); + session->state = UNINIT; + session->js = js; + session->remote_jid = g_strdup(session->id.initiator); + g_hash_table_insert(sessions, &(session->id), session); + + google_session_parse_iq(js, session, packet); +} + static void jabber_gmail_parse(JabberStream *js, xmlnode *packet, gpointer nul) { diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/jabber/google.h --- a/libpurple/protocols/jabber/google.h Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/jabber/google.h Wed Feb 06 19:44:41 2008 +0000 @@ -45,6 +45,7 @@ char *jabber_google_format_to_html(const char *text); +void jabber_google_session_parse(JabberStream *js, xmlnode *node); #endif /* _PURPLE_GOOGLE_H_ */ diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/jabber/iq.c --- a/libpurple/protocols/jabber/iq.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/jabber/iq.c Wed Feb 06 19:44:41 2008 +0000 @@ -337,6 +337,11 @@ return; } } + + if (xmlnode_get_child_with_namespace(packet, "session", "http://www.google.com/session")) { + jabber_google_session_parse(js, packet); + return; + } if(xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si")) { jabber_si_parse(js, packet); diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/jabber/jabber.c Wed Feb 06 19:44:41 2008 +0000 @@ -2332,6 +2332,13 @@ return TRUE; } +#ifdef USE_FARSIGHT +PurpleMedia *jabber_media_initiate(PurpleConnection *gc, const char *who, PurpleMediaStreamType type) +{ + return NULL; +} +#endif + void jabber_register_commands(void) { purple_cmd_register("config", "", PURPLE_CMD_P_PRPL, diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/jabber/jabber.h Wed Feb 06 19:44:41 2008 +0000 @@ -55,6 +55,7 @@ #include "dnssrv.h" #include "roomlist.h" #include "sslconn.h" +#include "media.h" #include "jutil.h" #include "xmlnode.h" @@ -263,4 +264,8 @@ void jabber_register_commands(void); void jabber_init_plugin(PurplePlugin *plugin); +#ifdef USE_FARSIGHT +PurpleMedia *jabber_media_initiate(PurpleConnection *gc, const char *who, PurpleMediaStreamType type); +#endif + #endif /* _PURPLE_JABBER_H_ */ diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/jabber/libxmpp.c --- a/libpurple/protocols/jabber/libxmpp.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Wed Feb 06 19:44:41 2008 +0000 @@ -115,9 +115,8 @@ jabber_unregister_account, /* unregister_user */ jabber_send_attention, /* send_attention */ jabber_attention_types, /* attention_types */ - - /* padding */ - NULL + sizeof(PurplePluginProtocolInfo), /* struct_size */ + jabber_media_initiate /* initiate_media */ }; static gboolean load_plugin(PurplePlugin *plugin) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/jabber/presence.c Wed Feb 06 19:44:41 2008 +0000 @@ -265,6 +265,10 @@ xmlnode_set_namespace(c, "http://jabber.org/protocol/caps"); xmlnode_set_attrib(c, "node", CAPS0115_NODE); xmlnode_set_attrib(c, "ver", VERSION); +#ifdef USE_FARSIGHT + /* Make sure this is 'voice-v1', or you won't be able to talk to Google Talk */ + xmlnode_set_attrib(c, "ext", "voice-v1"); +#endif if(js != NULL) { /* add the extensions */ diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/msn/Makefile.am --- a/libpurple/protocols/msn/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/msn/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -95,4 +95,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ - $(DEBUG_CFLAGS) + $(DEBUG_CFLAGS) \ + $(FARSIGHT_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/msn/msn.c --- a/libpurple/protocols/msn/msn.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/msn/msn.c Wed Feb 06 19:44:41 2008 +0000 @@ -2291,10 +2291,9 @@ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ msn_send_attention, /* send_attention */ - msn_attention_types, /* attention_types */ - - /* padding */ - NULL + msn_attention_types, /* get_attention_types */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; static PurplePluginInfo info = diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/msnp9/Makefile.am --- a/libpurple/protocols/msnp9/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/msnp9/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -87,4 +87,6 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ - $(DEBUG_CFLAGS) + $(DEBUG_CFLAGS) \ + $(FARSIGHT_CFLAGS) + diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/msnp9/msn.c --- a/libpurple/protocols/msnp9/msn.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/msnp9/msn.c Wed Feb 06 19:44:41 2008 +0000 @@ -2147,9 +2147,8 @@ NULL, /* unregister_user */ msn_send_attention, /* send_attention */ msn_attention_types, /* attention_types */ - - /* padding */ - NULL + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; static PurplePluginInfo info = diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/myspace/Makefile.am --- a/libpurple/protocols/myspace/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/myspace/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -40,4 +40,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(DEBUG_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/myspace/myspace.c --- a/libpurple/protocols/myspace/myspace.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/myspace/myspace.c Wed Feb 06 19:44:41 2008 +0000 @@ -3099,7 +3099,8 @@ NULL, /* unregister_user */ msim_send_attention, /* send_attention */ msim_attention_types, /* attention_types */ - NULL /* _purple_reserved4 */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/novell/Makefile.am --- a/libpurple/protocols/novell/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/novell/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -54,4 +54,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(DEBUG_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(GLIB_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/novell/novell.c --- a/libpurple/protocols/novell/novell.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/novell/novell.c Wed Feb 06 19:44:41 2008 +0000 @@ -3512,12 +3512,11 @@ NULL, /* whiteboard_prpl_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ - - /* padding */ - NULL, - NULL, - NULL, - NULL + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* get_attention_types */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; static PurplePluginInfo info = { diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/null/nullprpl.c --- a/libpurple/protocols/null/nullprpl.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/null/nullprpl.c Wed Feb 06 19:44:41 2008 +0000 @@ -1122,10 +1122,11 @@ NULL, /* whiteboard_prpl_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ - NULL, /* padding... */ - NULL, - NULL, - NULL, + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* get_attention_types */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; static void nullprpl_init(PurplePlugin *plugin) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/oscar/Makefile.am --- a/libpurple/protocols/oscar/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/oscar/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -76,4 +76,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(DEBUG_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/oscar/libaim.c --- a/libpurple/protocols/oscar/libaim.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/oscar/libaim.c Wed Feb 06 19:44:41 2008 +0000 @@ -92,12 +92,11 @@ NULL, /* whiteboard_prpl_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ - NULL, /* unregister_user */ - NULL, /* send_attention */ - NULL, /* get_attention_types */ - - /* padding */ - NULL + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* get_attention_types */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; static PurplePluginInfo info = diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/oscar/libicq.c --- a/libpurple/protocols/oscar/libicq.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/oscar/libicq.c Wed Feb 06 19:44:41 2008 +0000 @@ -92,12 +92,11 @@ NULL, /* whiteboard_prpl_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ - NULL, /* unregister_user */ - NULL, /* send_attention */ - NULL, /* get_attention_types */ - - /* padding */ - NULL + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* get_attention_types */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; static PurplePluginInfo info = diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/qq/Makefile.am --- a/libpurple/protocols/qq/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/qq/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -94,4 +94,5 @@ -I$(top_builddir)/libpurple \ -DQQ_BUDDY_ICON_DIR=\"$(datadir)/pixmaps/purple/buddy_icons/qq\" \ $(DEBUG_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(GLIB_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/qq/qq.c --- a/libpurple/protocols/qq/qq.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/qq/qq.c Wed Feb 06 19:44:41 2008 +0000 @@ -701,12 +701,11 @@ NULL, /* PurpleWhiteboardPrplOps */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ - - /* padding */ - NULL, - NULL, - NULL, - NULL + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* get_attention_types */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; static PurplePluginInfo info = { diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/sametime/Makefile.am --- a/libpurple/protocols/sametime/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/sametime/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -32,7 +32,7 @@ AM_CFLAGS = \ - $(GLIB_CFLAGS) $(MEANWHILE_CFLAGS) \ + $(GLIB_CFLAGS) $(MEANWHILE_CFLAGS) $(FARSIGHT_CFLAGS) \ $(DEBUG_CFLAGS) \ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/sametime/sametime.c --- a/libpurple/protocols/sametime/sametime.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/sametime/sametime.c Wed Feb 06 19:44:41 2008 +0000 @@ -5186,7 +5186,8 @@ .new_xfer = mw_prpl_new_xfer, .offline_message = NULL, .whiteboard_prpl_ops = NULL, - .send_raw = NULL + .send_raw = NULL, + .struct_size = sizeof(PurplePluginProtocolInfo) }; diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/silc/Makefile.am --- a/libpurple/protocols/silc/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/silc/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -25,7 +25,7 @@ noinst_LIBRARIES = libsilcpurple_la_SOURCES = $(SILCSOURCES) -libsilcpurple_la_LIBADD = $(GLIB_LIBS) $(SILC_LIBS) +libsilcpurple_la_LIBADD = $(GLIB_LIBS) $(SILC_LIBS) $(FARSIGHT_LIBS) endif @@ -33,4 +33,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(DEBUG_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/silc/silc.c --- a/libpurple/protocols/silc/silc.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/silc/silc.c Wed Feb 06 19:44:41 2008 +0000 @@ -1993,12 +1993,11 @@ &silcpurple_wb_ops, /* whiteboard_prpl_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ - - /* padding */ - NULL, - NULL, - NULL, - NULL + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* get_attention_types */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; static PurplePluginInfo info = diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/silc10/silc.c --- a/libpurple/protocols/silc10/silc.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/silc10/silc.c Wed Feb 06 19:44:41 2008 +0000 @@ -1799,12 +1799,11 @@ &silcpurple_wb_ops, /* whiteboard_prpl_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ - - /* padding */ - NULL, - NULL, - NULL, - NULL + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* get_attention_types */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; static PurplePluginInfo info = diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/simple/Makefile.am --- a/libpurple/protocols/simple/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/simple/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -33,4 +33,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(DEBUG_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/simple/simple.c --- a/libpurple/protocols/simple/simple.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/simple/simple.c Wed Feb 06 19:44:41 2008 +0000 @@ -2047,12 +2047,11 @@ NULL, /* whiteboard_prpl_ops */ simple_send_raw, /* send_raw */ NULL, /* roomlist_room_serialize */ - - /* padding */ - NULL, - NULL, - NULL, - NULL + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* get_attention_types */ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULL /* initiate_media */ }; diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/yahoo/Makefile.am --- a/libpurple/protocols/yahoo/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/yahoo/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -53,4 +53,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(DEBUG_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/yahoo/yahoo.c --- a/libpurple/protocols/yahoo/yahoo.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Wed Feb 06 19:44:41 2008 +0000 @@ -4328,11 +4328,9 @@ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ - yahoo_send_attention, yahoo_attention_types, - - /* padding */ + sizeof(PurplePluginProtocolInfo), NULL }; diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/zephyr/Makefile.am --- a/libpurple/protocols/zephyr/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/zephyr/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -106,5 +106,6 @@ -I$(top_srcdir)/libpurple/protocols \ -DCONFDIR=\"$(confdir)\" \ $(GLIB_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(KRB4_CFLAGS) \ $(DEBUG_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 libpurple/protocols/zephyr/zephyr.c --- a/libpurple/protocols/zephyr/zephyr.c Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/protocols/zephyr/zephyr.c Wed Feb 06 19:44:41 2008 +0000 @@ -2908,7 +2908,7 @@ NULL, NULL, NULL, - NULL + sizeof(PurplePluginProtocolInfo) }; static PurplePluginInfo info = { diff -r 762174f38807 -r f5bcb58bdf56 libpurple/prpl.h --- a/libpurple/prpl.h Wed Feb 06 15:50:41 2008 +0000 +++ b/libpurple/prpl.h Wed Feb 06 19:44:41 2008 +0000 @@ -64,6 +64,7 @@ #include "conversation.h" #include "ft.h" #include "imgstore.h" +#include "media.h" #include "notify.h" #include "proxy.h" #include "plugin.h" @@ -393,14 +394,25 @@ * reasons. */ void (*unregister_user)(PurpleAccount *, PurpleAccountUnregistrationCb cb, void *user_data); - + /* Attention API for sending & receiving zaps/nudges/buzzes etc. */ gboolean (*send_attention)(PurpleConnection *gc, const char *username, guint type); GList *(*get_attention_types)(PurpleAccount *acct); - void (*_purple_reserved4)(void); + /* Make sure you do not try to dereference anything past struct_size! */ + int struct_size; + +#ifdef USE_FARSIGHT + PurpleMedia *(*initiate_media)(PurpleConnection *conn, const char *who, PurpleMediaStreamType type); +#else + void (*initiate_media)(void); +#endif }; +#define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \ + ((G_STRUCT_OFFSET(PurplePluginProtocolInfo, member) < prpl->struct_size) && \ + prpl->member != NULL) + #define PURPLE_IS_PROTOCOL_PLUGIN(plugin) \ ((plugin)->info->type == PURPLE_PLUGIN_PROTOCOL) @@ -667,3 +679,4 @@ #endif #endif /* _PRPL_H_ */ + diff -r 762174f38807 -r f5bcb58bdf56 pidgin/Makefile.am --- a/pidgin/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/pidgin/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -99,6 +99,7 @@ gtkimhtmltoolbar.c \ gtklog.c \ gtkmain.c \ + gtkmedia.c \ gtkmenutray.c \ gtknotify.c \ gtkplugin.c \ @@ -150,6 +151,7 @@ gtkimhtml.h \ gtkimhtmltoolbar.h \ gtklog.h \ + gtkmedia.c \ gtkmenutray.h \ gtknickcolors.h \ gtknotify.h \ @@ -194,6 +196,7 @@ $(STARTUP_NOTIFICATION_LIBS) \ $(LIBXML_LIBS) \ $(GTK_LIBS) \ + $(FARSIGHT_LIBS) \ $(top_builddir)/libpurple/libpurple.la if USE_INTERNAL_LIBGADU @@ -218,5 +221,6 @@ $(GTKSPELL_CFLAGS) \ $(STARTUP_NOTIFICATION_CFLAGS) \ $(LIBXML_CFLAGS) \ - $(INTGG_CFLAGS) + $(INTGG_CFLAGS) \ + $(FARSIGHT_CFLAGS) endif # ENABLE_GTK diff -r 762174f38807 -r f5bcb58bdf56 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Wed Feb 06 15:50:41 2008 +0000 +++ b/pidgin/gtkconv.c Wed Feb 06 19:44:41 2008 +0000 @@ -46,6 +46,7 @@ #include "idle.h" #include "imgstore.h" #include "log.h" +#include "mediamanager.h" #include "notify.h" #include "prpl.h" #include "request.h" @@ -60,6 +61,7 @@ #include "gtkimhtml.h" #include "gtkimhtmltoolbar.h" #include "gtklog.h" +#include "gtkmedia.h" #include "gtkmenutray.h" #include "gtkpounce.h" #include "gtkprefs.h" @@ -4608,7 +4610,7 @@ GtkPolicyType imhtml_sw_hscroll; /* Setup the top part of the pane */ - vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); + gtkconv->topvbox = vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); gtk_widget_show(vbox); /* Setup the info pane */ @@ -7579,6 +7581,58 @@ return TRUE; } +static void +pidgin_gtkmedia_message_cb(PidginMedia *media, const char *msg, PurpleConversation *conv) +{ + purple_conv_im_write(PURPLE_CONV_IM(conv), NULL, msg, PURPLE_MESSAGE_SYSTEM, time(NULL)); +} + +static void +pidgin_conv_new_media_cb(PurpleMediaManager *manager, PurpleMedia *media, gpointer nul) +{ + GstElement *sendbin, *src, *sendlevel; + GstElement *recvbin, *sink, *recvlevel; + GstPad *pad, *ghost; + + GtkWidget *gtkmedia; + PurpleConversation *conv; + PidginConversation *gtkconv; + + sendbin = gst_bin_new("sendbin"); + src = gst_element_factory_make("alsasrc", "asrc"); + sendlevel = gst_element_factory_make("level", "sendlevel"); + gst_bin_add_many(GST_BIN(sendbin), src, sendlevel, NULL); + gst_element_link(src, sendlevel); //, gst_caps_new_simple("audio/x-raw-int", "rate", G_TYPE_INT, 8000, NULL)); + pad = gst_element_get_pad(sendlevel, "src"); + ghost = gst_ghost_pad_new("ghostsrc", pad); + gst_element_add_pad(sendbin, ghost); + g_object_set(G_OBJECT(sendlevel), "message", TRUE, NULL); + + recvbin = gst_bin_new("pidginrecvbin"); + sink = gst_element_factory_make("alsasink", "asink"); + g_object_set(G_OBJECT(sink), "sync", FALSE, NULL); + recvlevel = gst_element_factory_make("level", "recvlevel"); + gst_bin_add_many(GST_BIN(recvbin), sink, recvlevel, NULL); + gst_element_link(recvlevel, sink); + pad = gst_element_get_pad(recvlevel, "sink"); + ghost = gst_ghost_pad_new("ghostsink", pad); + gst_element_add_pad(recvbin, ghost); + g_object_set(G_OBJECT(recvlevel), "message", TRUE, NULL); + + purple_media_set_audio_src(media, sendbin); + purple_media_set_audio_sink(media, recvbin); + + gtkmedia = pidgin_media_new(media, sendlevel, recvlevel); + conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, + purple_connection_get_account(purple_media_get_connection(media)), + purple_media_get_screenname(media)); + gtkconv = PIDGIN_CONVERSATION(conv); + gtk_box_pack_start(GTK_BOX(gtkconv->topvbox), gtkmedia, FALSE, FALSE, 0); + gtk_widget_show(gtkmedia); + g_signal_connect_swapped(G_OBJECT(media), "got-hangup", G_CALLBACK(gtk_widget_destroy), gtkmedia); + g_signal_connect(G_OBJECT(gtkmedia), "message", G_CALLBACK(pidgin_gtkmedia_message_cb), conv); +} + void * pidgin_conversations_get_handle(void) { @@ -7675,6 +7729,8 @@ purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/im/hide_new", hide_new_pref_cb, NULL); + g_signal_connect(G_OBJECT(purple_media_manager_get()), "init-media", + G_CALLBACK(pidgin_conv_new_media_cb), NULL); /********************************************************************** diff -r 762174f38807 -r f5bcb58bdf56 pidgin/gtkconv.h --- a/pidgin/gtkconv.h Wed Feb 06 15:50:41 2008 +0000 +++ b/pidgin/gtkconv.h Wed Feb 06 19:44:41 2008 +0000 @@ -169,6 +169,7 @@ GtkWidget *infopane; GtkListStore *infopane_model; GtkTreeIter infopane_iter; + GtkWidget *topvbox; /* Used when attaching a PidginConversation to a PurpleConversation * with message history */ diff -r 762174f38807 -r f5bcb58bdf56 pidgin/gtkmedia.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtkmedia.c Wed Feb 06 19:44:41 2008 +0000 @@ -0,0 +1,322 @@ +/** + * @file media.c Account API + * @ingroup core + * + * Pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "internal.h" +#include "connection.h" +#include "media.h" + +#include "gtkmedia.h" + +#ifdef USE_FARSIGHT + +#include + +struct _PidginMediaPrivate +{ + PurpleMedia *media; + GstElement *send_level; + GstElement *recv_level; + + GtkWidget *accept; + GtkWidget *reject; + GtkWidget *hangup; + + GtkWidget *send_progress; + GtkWidget *recv_progress; +}; + +#define PIDGIN_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PIDGIN_TYPE_MEDIA, PidginMediaPrivate)) + +static void pidgin_media_class_init (PidginMediaClass *klass); +static void pidgin_media_init (PidginMedia *media); +static void pidgin_media_finalize (GObject *object); +static void pidgin_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static void pidgin_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); + +static GtkHBoxClass *parent_class = NULL; + + + +enum { + MESSAGE, + LAST_SIGNAL +}; +static guint pidgin_media_signals[LAST_SIGNAL] = {0}; + +enum { + PROP_0, + PROP_MEDIA, + PROP_SEND_LEVEL, + PROP_RECV_LEVEL +}; + +GType +pidgin_media_get_type() +{ + static GType type = 0; + + if (type == 0) { + static const GTypeInfo info = { + sizeof(PidginMediaClass), + NULL, + NULL, + (GClassInitFunc) pidgin_media_class_init, + NULL, + NULL, + sizeof(PidginMedia), + 0, + (GInstanceInitFunc) pidgin_media_init, + NULL + }; + type = g_type_register_static(GTK_TYPE_HBOX, "PidginMedia", &info, 0); + } + return type; +} + + +static void +pidgin_media_class_init (PidginMediaClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass*)klass; + GtkContainerClass *container_class = (GtkContainerClass*)klass; + parent_class = g_type_class_peek_parent(klass); + + gobject_class->finalize = pidgin_media_finalize; + gobject_class->set_property = pidgin_media_set_property; + gobject_class->get_property = pidgin_media_get_property; + + g_object_class_install_property(gobject_class, PROP_MEDIA, + g_param_spec_object("media", + "PurpleMedia", + "The PurpleMedia associated with this media.", + PURPLE_TYPE_MEDIA, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + g_object_class_install_property(gobject_class, PROP_SEND_LEVEL, + g_param_spec_object("send-level", + "Send level", + "The GstElement of this media's send 'level'", + GST_TYPE_ELEMENT, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + g_object_class_install_property(gobject_class, PROP_RECV_LEVEL, + g_param_spec_object("recv-level", + "Receive level", + "The GstElement of this media's recv 'level'", + GST_TYPE_ELEMENT, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + + pidgin_media_signals[MESSAGE] = g_signal_new("message", G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + + g_type_class_add_private(klass, sizeof(PidginMediaPrivate)); +} + + +static void +pidgin_media_init (PidginMedia *media) +{ + media->priv = PIDGIN_MEDIA_GET_PRIVATE(media); + media->priv->hangup = gtk_button_new_with_label("Hangup"); + media->priv->accept = gtk_button_new_with_label("Accept"); + media->priv->reject = gtk_button_new_with_label("Reject"); + media->priv->send_progress = gtk_progress_bar_new(); + media->priv->recv_progress = gtk_progress_bar_new(); + + gtk_widget_set_size_request(media->priv->send_progress, 70, 5); + gtk_widget_set_size_request(media->priv->recv_progress, 70, 5); + + gtk_box_pack_start(GTK_BOX(media), media->priv->hangup, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(media), media->priv->accept, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(media), media->priv->reject, FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(media), media->priv->send_progress, FALSE, FALSE, 6); + gtk_box_pack_start(GTK_BOX(media), media->priv->recv_progress, FALSE, FALSE, 6); + + gtk_widget_show(media->priv->send_progress); + gtk_widget_show(media->priv->recv_progress); + gtk_widget_show_all(media->priv->accept); + gtk_widget_show_all(media->priv->reject); +} + +static void +pidgin_media_finalize (GObject *media) +{ +} + +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; + const GValue *list; + const GValue *value; + + GstElement *src = GST_MESSAGE_SRC(message); + + if (message->type != GST_MESSAGE_ELEMENT) + return TRUE; + + s = gst_message_get_structure(message); + name = gst_structure_get_name(s); + + if (strcmp(name, "level")) + return TRUE; + + list = gst_structure_get_value(s, "rms"); + + /* Only bother with the first channel. */ + value = gst_value_list_get_value(list, 0); + rms_db = g_value_get_double(value); + + 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); + else + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(gtkmedia->priv->recv_progress), pow(10, rms_db / 20) * 5); + + return TRUE; +} + +static void +pidgin_media_ready_cb(PurpleMedia *media, PidginMedia *gtkmedia) +{ + GstElement *element = purple_media_get_audio_pipeline(media); + gst_bus_add_signal_watch(GST_BUS(gst_pipeline_get_bus(GST_PIPELINE(element)))); + g_signal_connect(G_OBJECT(gst_pipeline_get_bus(GST_PIPELINE(element))), "message", G_CALLBACK(level_message_cb), gtkmedia); + printf("\n\nbus: %p\n", gst_pipeline_get_bus(GST_PIPELINE(element))); +} + +static void +pidgin_media_accept_cb(PurpleMedia *media, PidginMedia *gtkmedia) +{ + pidgin_media_emit_message(gtkmedia, _("Call in progress.")); + gtk_widget_show(gtkmedia->priv->hangup); + gtk_widget_hide(gtkmedia->priv->accept); + gtk_widget_hide(gtkmedia->priv->reject); +} + +static void +pidgin_media_hangup_cb(PurpleMedia *media, PidginMedia *gtkmedia) +{ + pidgin_media_emit_message(gtkmedia, _("You have ended the call.")); + gtk_widget_destroy(GTK_WIDGET(gtkmedia)); +} + +static void +pidgin_media_reject_cb(PurpleMedia *media, PidginMedia *gtkmedia) +{ + pidgin_media_emit_message(gtkmedia, _("You have rejected the call.")); + gtk_widget_destroy(GTK_WIDGET(gtkmedia)); +} + +static void +pidgin_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + PidginMedia *media; + g_return_if_fail(PIDGIN_IS_MEDIA(object)); + + media = PIDGIN_MEDIA(object); + switch (prop_id) { + case PROP_MEDIA: + if (media->priv->media) + g_object_unref(media->priv->media); + media->priv->media = g_value_get_object(value); + g_object_ref(media->priv->media); + g_signal_connect_swapped(G_OBJECT(media->priv->accept), "clicked", + G_CALLBACK(purple_media_accept), media->priv->media); + g_signal_connect_swapped(G_OBJECT(media->priv->reject), "clicked", + G_CALLBACK(purple_media_reject), media->priv->media); + g_signal_connect_swapped(G_OBJECT(media->priv->hangup), "clicked", + G_CALLBACK(purple_media_hangup), media->priv->media); + + g_signal_connect(G_OBJECT(media->priv->media), "accepted", + G_CALLBACK(pidgin_media_accept_cb), media); + g_signal_connect(G_OBJECT(media->priv->media) ,"ready", + G_CALLBACK(pidgin_media_ready_cb), media); + g_signal_connect(G_OBJECT(media->priv->media), "hangup", + G_CALLBACK(pidgin_media_hangup_cb), media); + g_signal_connect(G_OBJECT(media->priv->media), "reject", + G_CALLBACK(pidgin_media_reject_cb), media); + break; + case PROP_SEND_LEVEL: + if (media->priv->send_level) + gst_object_unref(media->priv->send_level); + media->priv->send_level = g_value_get_object(value); + g_object_ref(media->priv->send_level); + break; + case PROP_RECV_LEVEL: + if (media->priv->recv_level) + gst_object_unref(media->priv->recv_level); + media->priv->recv_level = g_value_get_object(value); + g_object_ref(media->priv->recv_level); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +pidgin_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + PidginMedia *media; + g_return_if_fail(PIDGIN_IS_MEDIA(object)); + + media = PIDGIN_MEDIA(object); + + switch (prop_id) { + case PROP_MEDIA: + g_value_set_object(value, media->priv->media); + break; + case PROP_SEND_LEVEL: + g_value_set_object(value, media->priv->send_level); + break; + case PROP_RECV_LEVEL: + g_value_set_object(value, media->priv->recv_level); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +GtkWidget * +pidgin_media_new(PurpleMedia *media, GstElement *sendlevel, GstElement *recvlevel) +{ + return GTK_WIDGET(g_object_new(pidgin_media_get_type(), "media", media, "send-level", sendlevel, "recv-level", recvlevel, NULL)); +} + +#endif /* USE_FARSIGHT */ diff -r 762174f38807 -r f5bcb58bdf56 pidgin/gtkmedia.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtkmedia.h Wed Feb 06 19:44:41 2008 +0000 @@ -0,0 +1,74 @@ +/** + * @file media.h Account API + * @ingroup core + * + * Pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GTKMEDIA_H_ +#define __GTKMEDIA_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef USE_FARSIGHT + +#include +#include +#include + +#include "connection.h" + +G_BEGIN_DECLS + +#define PIDGIN_TYPE_MEDIA (pidgin_media_get_type()) +#define PIDGIN_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PIDGIN_TYPE_MEDIA, PidginMedia)) +#define PIDGIN_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PIDGIN_TYPE_MEDIA, PidginMediaClass)) +#define PIDGIN_IS_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PIDGIN_TYPE_MEDIA)) +#define PIDGIN_IS_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PIDGIN_TYPE_MEDIA)) +#define PIDGIN_MEDIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PIDGIN_TYPE_MEDIA, PidginMediaClass)) + +typedef struct _PidginMedia PidginMedia; +typedef struct _PidginMediaClass PidginMediaClass; +typedef struct _PidginMediaPrivate PidginMediaPrivate; + +struct _PidginMediaClass +{ + GtkHBoxClass parent_class; +}; + +struct _PidginMedia +{ + GtkHBox parent; + PidginMediaPrivate *priv; +}; + +GType pidgin_media_get_type(); + +GtkWidget *pidgin_media_new(PurpleMedia *media, GstElement *send_level, GstElement *recv_level); + +G_END_DECLS + +#endif /* USE_FARSIGHT */ + + +#endif /* __GTKMEDIA_H_ */ diff -r 762174f38807 -r f5bcb58bdf56 pidgin/plugins/Makefile.am --- a/pidgin/plugins/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/pidgin/plugins/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -119,6 +119,7 @@ -I$(top_srcdir)/libpurple \ -I$(top_srcdir)/pidgin \ $(DEBUG_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(GTK_CFLAGS) \ $(PLUGIN_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 pidgin/plugins/gestures/Makefile.am --- a/pidgin/plugins/gestures/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/pidgin/plugins/gestures/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -23,4 +23,5 @@ -I$(top_builddir)/libpurple \ -I$(top_srcdir)/pidgin \ $(DEBUG_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(GTK_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 pidgin/plugins/musicmessaging/Makefile.am --- a/pidgin/plugins/musicmessaging/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/pidgin/plugins/musicmessaging/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -40,5 +40,6 @@ -I$(top_srcdir)/libpurple \ -I$(top_srcdir)/pidgin \ $(DEBUG_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(GTK_CFLAGS) \ $(DBUS_CFLAGS) diff -r 762174f38807 -r f5bcb58bdf56 pidgin/plugins/ticker/Makefile.am --- a/pidgin/plugins/ticker/Makefile.am Wed Feb 06 15:50:41 2008 +0000 +++ b/pidgin/plugins/ticker/Makefile.am Wed Feb 06 19:44:41 2008 +0000 @@ -24,4 +24,5 @@ -I$(top_builddir)/libpurple \ -I$(top_srcdir)/pidgin \ $(DEBUG_CFLAGS) \ + $(FARSIGHT_CFLAGS) \ $(GTK_CFLAGS)