Mercurial > pidgin.yaz
changeset 26194:1fa62c559a78
merge of 'd47b8ff41e04be89d7152ac8f587e633fff7c1cb'
and 'e6e2272c5b1e49a6ee2565437cd3d6b8963085c9'
author | Mike Ruprecht <maiku@soc.pidgin.im> |
---|---|
date | Thu, 19 Feb 2009 11:28:01 +0000 |
parents | fcfb7571515c (diff) 260a606e2570 (current diff) |
children | 9fcff08ce726 |
files | |
diffstat | 10 files changed, 160 insertions(+), 95 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/media.c Wed Feb 11 22:42:29 2009 +0000 +++ b/libpurple/media.c Thu Feb 19 11:28:01 2009 +0000 @@ -69,6 +69,8 @@ gchar *participant; FsStream *stream; GstElement *sink; + GstElement *src; + GstElement *tee; GList *local_candidates; GList *remote_candidates; @@ -83,6 +85,7 @@ struct _PurpleMediaPrivate { + PurpleMediaManager *manager; FsConference *conference; gboolean initiator; @@ -129,6 +132,7 @@ enum { PROP_0, + PROP_MANAGER, PROP_CONFERENCE, PROP_INITIATOR, }; @@ -183,6 +187,13 @@ gobject_class->set_property = purple_media_set_property; gobject_class->get_property = purple_media_get_property; + g_object_class_install_property(gobject_class, PROP_MANAGER, + g_param_spec_object("manager", + "Purple Media Manager", + "The media manager that contains this media session.", + PURPLE_TYPE_MEDIA_MANAGER, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + g_object_class_install_property(gobject_class, PROP_CONFERENCE, g_param_spec_object("conference", "Farsight conference", @@ -276,8 +287,7 @@ purple_debug_info("media","purple_media_dispose\n"); - purple_media_manager_remove_media(purple_media_manager_get(), - PURPLE_MEDIA(media)); + purple_media_manager_remove_media(priv->manager, PURPLE_MEDIA(media)); if (priv->confbin) { gst_element_set_state(GST_ELEMENT(priv->confbin), @@ -312,6 +322,11 @@ g_object_unref(participants->data); } + if (priv->manager) { + g_object_unref(priv->manager); + priv->manager = NULL; + } + G_OBJECT_CLASS(parent_class)->finalize(media); } @@ -344,6 +359,10 @@ media = PURPLE_MEDIA(object); switch (prop_id) { + case PROP_MANAGER: + media->priv->manager = g_value_get_object(value); + g_object_ref(media->priv->manager); + break; case PROP_CONFERENCE: { gchar *name; @@ -384,6 +403,9 @@ media = PURPLE_MEDIA(object); switch (prop_id) { + case PROP_MANAGER: + g_value_set_object(value, media->priv->manager); + break; case PROP_CONFERENCE: g_value_set_object(value, media->priv->conference); break; @@ -1181,7 +1203,7 @@ } static gboolean -media_bus_call(GstBus *bus, GstMessage *msg, gpointer dummy) +media_bus_call(GstBus *bus, GstMessage *msg, PurpleMediaManager *manager) { switch(GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS: @@ -1206,7 +1228,7 @@ PurpleMedia *media = NULL; if (FS_IS_CONFERENCE(GST_MESSAGE_SRC(msg))) { GList *iter = purple_media_manager_get_media( - purple_media_manager_get()); + manager); for (; iter; iter = g_list_next(iter)) { if (PURPLE_MEDIA(iter->data)->priv->conference == FS_CONFERENCE(GST_MESSAGE_SRC(msg))) { @@ -1335,7 +1357,8 @@ bus = gst_pipeline_get_bus(GST_PIPELINE(media->priv->pipeline)); gst_bus_add_signal_watch(GST_BUS(bus)); g_signal_connect(G_OBJECT(bus), "message", - G_CALLBACK(media_bus_call), NULL); + G_CALLBACK(media_bus_call), + media->priv->manager); gst_bus_set_sync_handler(bus, gst_bus_sync_signal_handler, NULL); gst_object_unref(bus); gst_element_set_state(pipeline, GST_STATE_PLAYING); @@ -1576,7 +1599,7 @@ void purple_media_audio_init_recv(GstElement **recvbin, GstElement **recvlevel) { - GstElement *sink, *volume; + GstElement *sink, *volume, *queue; GstPad *pad, *ghost; double output_volume = purple_prefs_get_int( "/purple/media/audio/volume/output")/10.0; @@ -1589,10 +1612,13 @@ volume = gst_element_factory_make("volume", "purpleaudiooutputvolume"); g_object_set(volume, "volume", output_volume, NULL); *recvlevel = gst_element_factory_make("level", "recvlevel"); - gst_bin_add_many(GST_BIN(*recvbin), sink, volume, *recvlevel, NULL); + queue = gst_element_factory_make("queue", NULL); + gst_bin_add_many(GST_BIN(*recvbin), sink, volume, + *recvlevel, queue, NULL); gst_element_link(*recvlevel, sink); gst_element_link(volume, *recvlevel); - pad = gst_element_get_pad(volume, "sink"); + gst_element_link(queue, volume); + pad = gst_element_get_pad(queue, "sink"); ghost = gst_ghost_pad_new("ghostsink", pad); gst_element_add_pad(*recvbin, ghost); g_object_set(G_OBJECT(*recvlevel), "message", TRUE, NULL); @@ -1738,21 +1764,53 @@ purple_media_src_pad_added_cb(FsStream *fsstream, GstPad *srcpad, FsCodec *codec, PurpleMediaStream *stream) { - PurpleMediaSessionType type = purple_media_from_fs(codec->media_type, FS_DIRECTION_RECV); - GstPad *sinkpad = NULL; + PurpleMediaPrivate *priv; + GstPad *sinkpad; g_return_if_fail(FS_IS_STREAM(fsstream)); g_return_if_fail(stream != NULL); - if (stream->sink == NULL) - stream->sink = purple_media_manager_get_element( - purple_media_manager_get(), type); - - gst_bin_add(GST_BIN(stream->session->media->priv->confbin), - stream->sink); - sinkpad = gst_element_get_static_pad(stream->sink, "ghostsink"); + priv = stream->session->media->priv; + + if (stream->src == NULL) { + GstElement *sink; + + if (codec->media_type == FS_MEDIA_TYPE_AUDIO) { + /* + * Should this instead be: + * audioconvert ! audioresample ! liveadder ! + * audioresample ! audioconvert ! realsink + */ + stream->src = gst_element_factory_make( + "liveadder", NULL); + sink = purple_media_manager_get_element(priv->manager, + PURPLE_MEDIA_RECV_AUDIO); + } else if (codec->media_type == FS_MEDIA_TYPE_VIDEO) { + stream->src = gst_element_factory_make( + "fsfunnel", NULL); + sink = gst_element_factory_make( + "fakesink", NULL); + g_object_set(G_OBJECT(sink), "async", FALSE, NULL); + } + stream->tee = gst_element_factory_make("tee", NULL); + gst_bin_add_many(GST_BIN(priv->confbin), + stream->src, stream->tee, sink, NULL); + gst_element_sync_state_with_parent(sink); + gst_element_sync_state_with_parent(stream->tee); + gst_element_sync_state_with_parent(stream->src); + gst_element_link_many(stream->src, stream->tee, sink, NULL); + } + + sinkpad = gst_element_get_request_pad(stream->src, "sink%d"); gst_pad_link(srcpad, sinkpad); - gst_element_set_state(stream->sink, GST_STATE_PLAYING); + gst_object_unref(sinkpad); + + if (codec->media_type == FS_MEDIA_TYPE_VIDEO && + stream->sink != NULL) { + gst_bin_add(GST_BIN(priv->confbin), stream->sink); + gst_element_set_state(stream->sink, GST_STATE_PLAYING); + gst_element_link(stream->tee, stream->sink); + } g_timeout_add_full(G_PRIORITY_HIGH, 0, (GSourceFunc)purple_media_connected_cb, stream, NULL); @@ -1841,7 +1899,7 @@ session_type = purple_media_from_fs(type, FS_DIRECTION_SEND); purple_media_set_src(media, session->id, purple_media_manager_get_element( - purple_media_manager_get(), session_type)); + media->priv->manager, session_type)); gst_element_set_state(session->src, GST_STATE_PLAYING); } @@ -2376,7 +2434,7 @@ PurpleMediaStream *stream = purple_media_get_stream( media, session_id, participant); GstBus *bus; - GstElement *bin, *sink; + GstElement *bin, *queue, *sink; GstPad *pad, *peer = NULL, *ghostpad; PurpleMediaXOverlayData *data; gchar *name; @@ -2423,10 +2481,12 @@ name = g_strdup_printf("stream-sink_%s_%s", session_id, participant); + queue = gst_element_factory_make("queue", NULL); sink = gst_element_factory_make("autovideosink", name); - gst_bin_add(GST_BIN(bin), sink); - pad = gst_element_get_static_pad(sink, "sink"); + gst_bin_add_many(GST_BIN(bin), queue, sink, NULL); + gst_element_link(queue, sink); + pad = gst_element_get_static_pad(queue, "sink"); ghostpad = gst_ghost_pad_new("ghostsink", pad); gst_element_add_pad(bin, ghostpad); @@ -2442,9 +2502,11 @@ G_CALLBACK(window_id_cb), data); gst_object_unref(bus); - if (stream->sink != NULL) { + if (stream->tee != NULL) { + gst_bin_add(GST_BIN(GST_ELEMENT_PARENT( + stream->tee)), bin); gst_element_set_state(bin, GST_STATE_PLAYING); - gst_pad_link(peer, ghostpad); + gst_element_link(stream->tee, bin); } stream->sink = bin;
--- a/libpurple/media.h Wed Feb 11 22:42:29 2009 +0000 +++ b/libpurple/media.h Thu Feb 19 11:28:01 2009 +0000 @@ -65,6 +65,18 @@ #endif /* USE_VV */ +/** Media caps */ +typedef enum { + PURPLE_MEDIA_CAPS_NONE = 0, + PURPLE_MEDIA_CAPS_AUDIO = 1, + PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION = 1 << 1, + PURPLE_MEDIA_CAPS_VIDEO = 1 << 2, + PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION = 1 << 3, + PURPLE_MEDIA_CAPS_AUDIO_VIDEO = 1 << 4, + PURPLE_MEDIA_CAPS_MODIFY_SESSION = 1 << 5, + PURPLE_MEDIA_CAPS_CHANGE_DIRECTION = 1 << 6, +} PurpleMediaCaps; + /** Media session types */ typedef enum { PURPLE_MEDIA_NONE = 0,
--- a/libpurple/mediamanager.c Wed Feb 11 22:42:29 2009 +0000 +++ b/libpurple/mediamanager.c Thu Feb 19 11:28:01 2009 +0000 @@ -165,6 +165,7 @@ } media = PURPLE_MEDIA(g_object_new(purple_media_get_type(), + "manager", manager, "conference", conference, "initiator", initiator, NULL));
--- a/libpurple/protocols/jabber/jabber.c Wed Feb 11 22:42:29 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Thu Feb 19 11:28:01 2009 +0000 @@ -2591,11 +2591,11 @@ return jingle_rtp_initiate_media(gc->proto_data, who, type); } -gboolean jabber_can_do_media(PurpleConnection *gc, const char *who, - PurpleMediaSessionType type) +PurpleMediaCaps jabber_get_media_caps(PurpleConnection *gc, const char *who) { JabberStream *js = (JabberStream *) gc->proto_data; JabberBuddy *jb; + PurpleMediaCaps caps = PURPLE_MEDIA_CAPS_NONE; if (!js) { purple_debug_error("jabber", "jabber_can_do_media: NULL stream\n"); @@ -2609,34 +2609,30 @@ return FALSE; } - if (!jabber_buddy_has_capability(jb, JINGLE_TRANSPORT_ICEUDP) && - !jabber_buddy_has_capability(jb, - JINGLE_TRANSPORT_RAWUDP) && - !jabber_buddy_has_capability(jb, GTALK_CAP)) { - purple_debug_info("jingle-rtp", "Buddy doesn't support " - "the same transport types\n"); - return FALSE; + if (jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_AUDIO)) + caps |= PURPLE_MEDIA_CAPS_AUDIO | + PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION; + if (jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_VIDEO)) + caps |= PURPLE_MEDIA_CAPS_VIDEO | + PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION; + if (caps & PURPLE_MEDIA_CAPS_AUDIO && caps & PURPLE_MEDIA_CAPS_VIDEO) + caps |= PURPLE_MEDIA_CAPS_AUDIO_VIDEO; + if (caps != PURPLE_MEDIA_CAPS_NONE) { + if (!jabber_buddy_has_capability(jb, + JINGLE_TRANSPORT_ICEUDP) && + !jabber_buddy_has_capability(jb, + JINGLE_TRANSPORT_RAWUDP)) { + purple_debug_info("jingle-rtp", "Buddy doesn't " + "support the same transport types\n"); + caps = PURPLE_MEDIA_CAPS_NONE; + } else + caps |= PURPLE_MEDIA_CAPS_MODIFY_SESSION | + PURPLE_MEDIA_CAPS_CHANGE_DIRECTION; } - - /* XMPP will only support two-way media, AFAIK... */ - if (type == (PURPLE_MEDIA_AUDIO | PURPLE_MEDIA_VIDEO)) { - purple_debug_info("jabber", - "Checking audio/video XEP support for %s\n", who); - return (jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_AUDIO) || - jabber_buddy_has_capability(jb, GTALK_CAP)) && - jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_VIDEO); - } else if (type == (PURPLE_MEDIA_AUDIO)) { - purple_debug_info("jabber", - "Checking audio XEP support for %s\n", who); - return jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_AUDIO) || - jabber_buddy_has_capability(jb, GTALK_CAP); - } else if (type == (PURPLE_MEDIA_VIDEO)) { - purple_debug_info("jabber", - "Checking video XEP support for %s\n", who); - return jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_VIDEO); - } - - return FALSE; + if (jabber_buddy_has_capability(jb, GTALK_CAP)) + caps |= PURPLE_MEDIA_CAPS_AUDIO; + + return caps; } #endif
--- a/libpurple/protocols/jabber/jabber.h Wed Feb 11 22:42:29 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.h Thu Feb 19 11:28:01 2009 +0000 @@ -329,7 +329,7 @@ #ifdef USE_VV PurpleMedia *jabber_initiate_media(PurpleConnection *gc, const char *who, PurpleMediaSessionType type); -gboolean jabber_can_do_media(PurpleConnection *gc, const char *who, PurpleMediaSessionType type); +PurpleMediaCaps jabber_get_media_caps(PurpleConnection *gc, const char *who); #endif #endif /* _PURPLE_JABBER_H_ */
--- a/libpurple/protocols/jabber/libxmpp.c Wed Feb 11 22:42:29 2009 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Thu Feb 19 11:28:01 2009 +0000 @@ -120,7 +120,7 @@ NULL, /* get_account_text_table */ #ifdef USE_VV jabber_initiate_media, /* initiate_media */ - jabber_can_do_media /* can_do_media */ + jabber_get_media_caps, /* get_media_caps */ #else NULL, /* initiate_media */ NULL /* can_do_media */
--- a/libpurple/prpl.c Wed Feb 11 22:42:29 2009 +0000 +++ b/libpurple/prpl.c Thu Feb 19 11:28:01 2009 +0000 @@ -524,10 +524,8 @@ #endif } -gboolean -purple_prpl_can_do_media(PurpleAccount *account, - const char *who, - PurpleMediaSessionType type) +PurpleMediaCaps +purple_prpl_get_media_caps(PurpleAccount *account, const char *who) { #ifdef USE_VV PurpleConnection *gc = NULL; @@ -541,14 +539,12 @@ if (prpl) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, can_do_media)) { - return prpl_info->can_do_media(gc, who, type); - } else { - return FALSE; + if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, + get_media_caps)) { + return prpl_info->get_media_caps(gc, who); } -#else - return FALSE; #endif + return PURPLE_MEDIA_CAPS_NONE; } /**************************************************************************
--- a/libpurple/prpl.h Wed Feb 11 22:42:29 2009 +0000 +++ b/libpurple/prpl.h Thu Feb 19 11:28:01 2009 +0000 @@ -466,11 +466,10 @@ * * @param conn The connection the contact is on. * @param who The remote user to check for media capability with. - * @param type The type of media session to check for. - * @return @c TRUE The contact supports the given media type, or @c FALSE otherwise. + * @return The media caps the contact supports. */ - gboolean (*can_do_media)(PurpleConnection *gc, const char *who, - PurpleMediaSessionType type); + PurpleMediaCaps (*get_media_caps)(PurpleConnection *gc, + const char *who); }; #define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \ @@ -765,13 +764,11 @@ * * @param account The account the user is on. * @param who The name of the contact to check capabilities for. - * @param type The type of media session to check for. * - * @return @c TRUE if the contact supports the session type, else @c FALSE. + * @return The media caps the contact supports. */ -gboolean purple_prpl_can_do_media(PurpleAccount *account, - const char *who, - PurpleMediaSessionType type); +PurpleMediaCaps purple_prpl_get_media_caps(PurpleAccount *account, + const char *who); /** * Initiates a media session with the given contact.
--- a/pidgin/gtkblist.c Wed Feb 11 22:42:29 2009 +0000 +++ b/pidgin/gtkblist.c Thu Feb 19 11:28:01 2009 +0000 @@ -348,8 +348,9 @@ { /* if the buddy supports both audio and video, start a combined call, otherwise start a pure video session */ - if (purple_prpl_can_do_media(purple_buddy_get_account(b), - purple_buddy_get_name(b), PURPLE_MEDIA_AUDIO)) { + if (purple_prpl_get_media_caps(purple_buddy_get_account(b), + purple_buddy_get_name(b)) & + PURPLE_MEDIA_CAPS_AUDIO_VIDEO) { purple_prpl_initiate_media(purple_buddy_get_account(b), purple_buddy_get_name(b), PURPLE_MEDIA_AUDIO | PURPLE_MEDIA_VIDEO); } else { @@ -1463,20 +1464,20 @@ G_CALLBACK(gtk_blist_menu_im_cb), buddy, 0, 0, NULL); #ifdef USE_VV - if (prpl_info && prpl_info->can_do_media) { - PurpleConnection *gc = - purple_account_get_connection(purple_buddy_get_account(buddy)); + if (prpl_info && prpl_info->get_media_caps) { + PurpleAccount *account = purple_buddy_get_account(buddy); const gchar *who = purple_buddy_get_name(buddy); - if (prpl_info->can_do_media(gc, who, PURPLE_MEDIA_AUDIO)) { + PurpleMediaCaps caps = purple_prpl_get_media_caps(account, who); + if (caps & PURPLE_MEDIA_CAPS_AUDIO) { pidgin_new_item_from_stock(menu, _("_Audio Call"), PIDGIN_STOCK_TOOLBAR_AUDIO_CALL, G_CALLBACK(gtk_blist_menu_audio_call_cb), buddy, 0, 0, NULL); } - if (prpl_info->can_do_media(gc, who, PURPLE_MEDIA_VIDEO | PURPLE_MEDIA_AUDIO)) { + if (caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO) { pidgin_new_item_from_stock(menu, _("Audio/_Video Call"), PIDGIN_STOCK_TOOLBAR_VIDEO_CALL, G_CALLBACK(gtk_blist_menu_video_call_cb), buddy, 0, 0, NULL); - } else if (prpl_info->can_do_media(gc, who, PURPLE_MEDIA_VIDEO)) { + } else if (caps & PURPLE_MEDIA_CAPS_VIDEO) { pidgin_new_item_from_stock(menu, _("_Video Call"), PIDGIN_STOCK_TOOLBAR_VIDEO_CALL, G_CALLBACK(gtk_blist_menu_video_call_cb), buddy, 0, 0, NULL);
--- a/pidgin/gtkconv.c Wed Feb 11 22:42:29 2009 +0000 +++ b/pidgin/gtkconv.c Thu Feb 19 11:28:01 2009 +0000 @@ -6446,19 +6446,19 @@ supports it */ if (account != NULL && purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - gboolean audio = purple_prpl_can_do_media(account, - purple_conversation_get_name(conv), - PURPLE_MEDIA_AUDIO); - gboolean video = purple_prpl_can_do_media(account, - purple_conversation_get_name(conv), - PURPLE_MEDIA_VIDEO); - gboolean av = purple_prpl_can_do_media(account, - purple_conversation_get_name(conv), - PURPLE_MEDIA_AUDIO | PURPLE_MEDIA_VIDEO); - - gtk_widget_set_sensitive(win->menu.audio_call, audio ? TRUE : FALSE); - gtk_widget_set_sensitive(win->menu.video_call, video ? TRUE : FALSE); - gtk_widget_set_sensitive(win->menu.audio_video_call, av ? TRUE : FALSE); + PurpleMediaCaps caps = + purple_prpl_get_media_caps(account, + purple_conversation_get_name(conv)); + + gtk_widget_set_sensitive(win->menu.audio_call, + caps & PURPLE_MEDIA_CAPS_AUDIO + ? TRUE : FALSE); + gtk_widget_set_sensitive(win->menu.video_call, + caps & PURPLE_MEDIA_CAPS_VIDEO + ? TRUE : FALSE); + gtk_widget_set_sensitive(win->menu.audio_video_call, + caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO + ? TRUE : FALSE); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { /* for now, don't care about chats... */ gtk_widget_set_sensitive(win->menu.audio_call, FALSE);