# HG changeset patch # User Sean Egan # Date 1190242519 0 # Node ID 70cdff43ec76fdd9b137e963b9ed2b312c7e28b9 # Parent 2fda7113380058a0d8430bfbf1fac45e74e0e3c0 You can actually receive Google Talk voice calls with crappy UI now diff -r 2fda71133800 -r 70cdff43ec76 libpurple/media.c --- a/libpurple/media.c Wed Sep 05 01:55:16 2007 +0000 +++ b/libpurple/media.c Wed Sep 19 22:55:19 2007 +0000 @@ -23,6 +23,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include + #include "connection.h" #include "media.h" @@ -36,6 +38,13 @@ 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)) @@ -51,7 +60,11 @@ enum { - STATE_CHANGE, + READY, + ACCEPTED, + HANGUP, + REJECT, + GOT_HANGUP, LAST_SIGNAL }; static guint purple_media_signals[LAST_SIGNAL] = {0}; @@ -61,8 +74,12 @@ PROP_FARSIGHT_SESSION, PROP_NAME, PROP_CONNECTION, - PROP_MIC_ELEMENT, - PROP_SPEAKER_ELEMENT, + PROP_AUDIO_SRC, + PROP_AUDIO_SINK, + PROP_VIDEO_SRC, + PROP_VIDEO_SINK, + PROP_VIDEO_STREAM, + PROP_AUDIO_STREAM }; GType @@ -103,26 +120,93 @@ "Farsight session", "The FarsightSession associated with this media.", FARSIGHT_TYPE_SESSION, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READABLE)); + 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_READABLE)); + 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_READABLE)); + 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 @@ -141,14 +225,55 @@ 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: - media->priv->name = g_value_get_string(value); + 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; @@ -173,6 +298,25 @@ 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; @@ -180,4 +324,132 @@ } +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 2fda71133800 -r 70cdff43ec76 libpurple/media.h --- a/libpurple/media.h Wed Sep 05 01:55:16 2007 +0000 +++ b/libpurple/media.h Wed Sep 19 22:55:19 2007 +0000 @@ -71,6 +71,28 @@ GType purple_media_get_type(); +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(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 */ diff -r 2fda71133800 -r 70cdff43ec76 libpurple/mediamanager.c --- a/libpurple/mediamanager.c Wed Sep 05 01:55:16 2007 +0000 +++ b/libpurple/mediamanager.c Wed Sep 19 22:55:19 2007 +0000 @@ -47,7 +47,7 @@ enum { - NEW_MEDIA, + INIT_MEDIA, LAST_SIGNAL }; static guint purple_media_manager_signals[LAST_SIGNAL] = {0}; @@ -92,7 +92,7 @@ gobject_class->finalize = purple_media_manager_finalize; - purple_media_manager_signals[NEW_MEDIA] = g_signal_new ("new-media", + purple_media_manager_signals[INIT_MEDIA] = g_signal_new ("init-media", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, @@ -127,13 +127,17 @@ PurpleMedia* purple_media_manager_create_media(PurpleMediaManager *manager, PurpleConnection *gc, - const char *screenname) + const char *screenname, + FarsightStream *audio_stream, + FarsightStream *video_stream) { PurpleMedia *media = PURPLE_MEDIA(g_object_new(purple_media_get_type(), "screenname", screenname, - "connection", gc, NULL)); + "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[NEW_MEDIA], 0, media); + g_signal_emit(manager, purple_media_manager_signals[INIT_MEDIA], 0, media); return media; } diff -r 2fda71133800 -r 70cdff43ec76 libpurple/mediamanager.h --- a/libpurple/mediamanager.h Wed Sep 05 01:55:16 2007 +0000 +++ b/libpurple/mediamanager.h Wed Sep 19 22:55:19 2007 +0000 @@ -68,7 +68,9 @@ PurpleMedia *purple_media_manager_create_media(PurpleMediaManager *manager, PurpleConnection *gc, - const char *screenname); + const char *screenname, + FarsightStream *audio_stream, + FarsightStream *video_stream); G_END_DECLS diff -r 2fda71133800 -r 70cdff43ec76 libpurple/protocols/jabber/google.c --- a/libpurple/protocols/jabber/google.c Wed Sep 05 01:55:16 2007 +0000 +++ b/libpurple/protocols/jabber/google.c Wed Sep 19 22:55:19 2007 +0000 @@ -54,6 +54,7 @@ char *remote_jid; } GoogleSession; +GHashTable *sessions = NULL; static guint google_session_id_hash(gconstpointer key) @@ -75,7 +76,17 @@ return !strcmp(c->id, d->id) && !strcmp(c->initiator, d->initiator); } -GHashTable *sessions = NULL; +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) @@ -116,6 +127,39 @@ 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) { @@ -159,10 +203,11 @@ jabber_iq_send(iq); } -static gboolean -google_session_handle_initiate(JabberStream *js, GoogleSession *session, xmlnode *packet) +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; @@ -185,7 +230,7 @@ g_object_set(G_OBJECT(session->stream), "transmitter", "libjingle", NULL); - desc_element = xmlnode_get_child(packet, "description"); + desc_element = xmlnode_get_child(sess, "description"); for (codec_element = xmlnode_get_child(desc_element, "payload-type"); codec_element; @@ -198,30 +243,37 @@ farsight_codec_init(codec, atoi(id), encoding_name, FARSIGHT_MEDIA_TYPE_AUDIO, clock_rate ? atoi(clock_rate) : 0); codecs = g_list_append(codecs, codec); } - GstElement *e = gst_element_factory_make("alsasrc", "source"); - farsight_stream_set_source(session->stream, e); - farsight_stream_set_source_filter(session->stream, gst_caps_new_simple("audio/x-raw-int", "rate",G_TYPE_INT,8000, NULL)); - gst_object_unref(e); + + 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); - e = gst_element_factory_make("alsasink", "fakes"); - g_object_set(e, "sync", FALSE, NULL); + + 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); - gst_object_unref(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); -google_session_send_accept(session); - media = purple_media_manager_create_media(purple_media_manager_get(), js->gc, session->remote_jid); - return res; + 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 gboolean -google_session_handle_candidates(JabberStream *js, GoogleSession *session, xmlnode *sess) +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; @@ -246,31 +298,46 @@ farsight_stream_add_remote_candidate(session->stream, list); g_list_foreach(list, g_free, NULL); g_list_free(list); - return TRUE; + + 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) { - JabberIq *result; - gboolean valid = TRUE; xmlnode *sess = xmlnode_get_child(packet, "session"); const char *type = xmlnode_get_attrib(sess, "type"); if (!strcmp(type, "initiate")) { - valid = google_session_handle_initiate(js, session, sess); + 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")) { - valid = google_session_handle_candidates(js, session, sess); - } - - if (valid) { - 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); + google_session_handle_candidates(js, session, packet, sess); } } diff -r 2fda71133800 -r 70cdff43ec76 pidgin/Makefile.am --- a/pidgin/Makefile.am Wed Sep 05 01:55:16 2007 +0000 +++ b/pidgin/Makefile.am Wed Sep 19 22:55:19 2007 +0000 @@ -96,6 +96,7 @@ gtkimhtmltoolbar.c \ gtklog.c \ gtkmain.c \ + gtkmedia.c \ gtkmenutray.c \ gtknotify.c \ gtkplugin.c \ @@ -144,6 +145,7 @@ gtkimhtml.h \ gtkimhtmltoolbar.h \ gtklog.h \ + gtkmedia.c \ gtkmenutray.h \ gtknickcolors.h \ gtknotify.h \ diff -r 2fda71133800 -r 70cdff43ec76 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Wed Sep 05 01:55:16 2007 +0000 +++ b/pidgin/gtkconv.c Wed Sep 19 22:55:19 2007 +0000 @@ -60,6 +60,7 @@ #include "gtkimhtml.h" #include "gtkimhtmltoolbar.h" #include "gtklog.h" +#include "gtkmedia.h" #include "gtkmenutray.h" #include "gtkpounce.h" #include "gtkprefs.h" @@ -4490,7 +4491,7 @@ gtk_widget_show(paned); /* 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_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE); gtk_widget_show(vbox); @@ -7163,9 +7164,55 @@ } static void -pidgin_conv_new_media_cb(PurpleMedia *media, gpointer nul) -{ - purple_notify_info(pidgin_conversations_get_handle(), "Media!", "New Media!", "You got new media!\n"); +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 * @@ -7264,7 +7311,7 @@ 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()), "new-media", + g_signal_connect(G_OBJECT(purple_media_manager_get()), "init-media", G_CALLBACK(pidgin_conv_new_media_cb), NULL); diff -r 2fda71133800 -r 70cdff43ec76 pidgin/gtkconv.h --- a/pidgin/gtkconv.h Wed Sep 05 01:55:16 2007 +0000 +++ b/pidgin/gtkconv.h Wed Sep 19 22:55:19 2007 +0000 @@ -162,6 +162,7 @@ GtkWidget *infopane; GtkListStore *infopane_model; GtkTreeIter infopane_iter; + GtkWidget *topvbox; }; /*@}*/