# HG changeset patch # User maiku@pidgin.im # Date 1256254191 0 # Node ID 4aa30863743b0f008bf669d2bd64a3b7c7fed681 # Parent af08588c06f5d7efcb03b2eb66ee1b65c96c356a Create and dispose the conference in the Farsight 2 media backend. diff -r af08588c06f5 -r 4aa30863743b libpurple/media/backend-fs2.c --- a/libpurple/media/backend-fs2.c Thu Oct 22 22:58:48 2009 +0000 +++ b/libpurple/media/backend-fs2.c Thu Oct 22 23:29:51 2009 +0000 @@ -27,6 +27,10 @@ #include "backend-fs2.h" #include "backend-iface.h" +#include "debug.h" +#include "media-gst.h" + +#include /** @copydoc _PurpleMediaBackendFs2Class */ typedef struct _PurpleMediaBackendFs2Class PurpleMediaBackendFs2Class; @@ -39,6 +43,9 @@ static void purple_media_backend_iface_init(PurpleMediaBackendIface *iface); +static gboolean +_gst_bus_cb(GstBus *bus, GstMessage *msg, PurpleMediaBackend *self); + static gboolean purple_media_backend_fs2_add_stream(PurpleMediaBackend *self, const gchar *sess_id, const gchar *who, PurpleMediaSessionType type, gboolean initiator, @@ -77,10 +84,14 @@ struct _PurpleMediaBackendFs2Private { PurpleMedia *media; + GstElement *confbin; + FsConference *conference; + gchar *conference_type; }; enum { PROP_0, + PROP_CONFERENCE_TYPE, PROP_MEDIA, }; @@ -90,8 +101,53 @@ } static void +purple_media_backend_fs2_dispose(GObject *obj) +{ + PurpleMediaBackendFs2Private *priv = + PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(obj); + + if (priv->confbin) { + GstElement *pipeline; + + pipeline = purple_media_manager_get_pipeline( + purple_media_get_manager(priv->media)); + + gst_element_set_locked_state(priv->confbin, TRUE); + gst_element_set_state(GST_ELEMENT(priv->confbin), + GST_STATE_NULL); + + if (pipeline) { + GstBus *bus; + gst_bin_remove(GST_BIN(pipeline), priv->confbin); + bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); + g_signal_handlers_disconnect_matched(G_OBJECT(bus), + G_SIGNAL_MATCH_FUNC | + G_SIGNAL_MATCH_DATA, + 0, 0, 0, _gst_bus_cb, obj); + gst_object_unref(bus); + } else { + purple_debug_warning("backend-fs2", "Unable to " + "properly dispose the conference. " + "Couldn't get the pipeline.\n"); + } + + priv->confbin = NULL; + priv->conference = NULL; + + } + + if (priv->media) { + g_object_unref(priv->media); + priv->media = NULL; + } +} + +static void purple_media_backend_fs2_finalize(GObject *obj) { + PurpleMediaBackendFs2Private *priv = + PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(obj); + g_free(priv->conference_type); } static void @@ -104,6 +160,9 @@ priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(object); switch (prop_id) { + case PROP_CONFERENCE_TYPE: + priv->conference_type = g_value_dup_string(value); + break; case PROP_MEDIA: priv->media = g_value_dup_object(value); break; @@ -124,6 +183,9 @@ priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(object); switch (prop_id) { + case PROP_CONFERENCE_TYPE: + g_value_set_string(value, priv->conference_type); + break; case PROP_MEDIA: g_value_set_object(value, priv->media); break; @@ -137,13 +199,15 @@ static void purple_media_backend_fs2_class_init(PurpleMediaBackendFs2Class *klass) { - GObjectClass *gobject_class = (GObjectClass*)klass; - + + gobject_class->dispose = purple_media_backend_fs2_dispose; gobject_class->finalize = purple_media_backend_fs2_finalize; gobject_class->set_property = purple_media_backend_fs2_set_property; gobject_class->get_property = purple_media_backend_fs2_get_property; + g_object_class_override_property(gobject_class, PROP_CONFERENCE_TYPE, + "conference-type"); g_object_class_override_property(gobject_class, PROP_MEDIA, "media"); g_type_class_add_private(klass, sizeof(PurpleMediaBackendFs2Private)); @@ -163,13 +227,99 @@ } static gboolean +_gst_bus_cb(GstBus *bus, GstMessage *msg, PurpleMediaBackend *self) +{ + return TRUE; +} + +static gboolean +_init_conference(PurpleMediaBackend *self) +{ + PurpleMediaBackendFs2Private *priv = + PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); + GstElement *pipeline; + GstBus *bus; + gchar *name; + + priv->conference = FS_CONFERENCE( + gst_element_factory_make(priv->conference_type, NULL)); + + if (priv->conference == NULL) { + purple_debug_error("backend-fs2", "Conference == NULL\n"); + return FALSE; + } + + pipeline = purple_media_manager_get_pipeline( + purple_media_manager_get()); + + if (pipeline == NULL) { + purple_debug_error("backend-fs2", + "Couldn't retrieve pipeline.\n"); + return FALSE; + } + + name = g_strdup_printf("conf_%p", priv->conference); + priv->confbin = gst_bin_new(name); + if (priv->confbin == NULL) { + purple_debug_error("backend-fs2", + "Couldn't create confbin.\n"); + return FALSE; + } + + g_free(name); + + bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); + if (bus == NULL) { + purple_debug_error("backend-fs2", + "Couldn't get the pipeline's bus.\n"); + return FALSE; + } + + g_signal_connect(G_OBJECT(bus), "message", + G_CALLBACK(_gst_bus_cb), self); + gst_object_unref(bus); + + if (!gst_bin_add(GST_BIN(pipeline), + GST_ELEMENT(priv->confbin))) { + purple_debug_error("backend-fs2", "Couldn't add confbin " + "element to the pipeline\n"); + return FALSE; + } + + if (!gst_bin_add(GST_BIN(priv->confbin), + GST_ELEMENT(priv->conference))) { + purple_debug_error("backend-fs2", "Couldn't add conference " + "element to the confbin\n"); + return FALSE; + } + + if (gst_element_set_state(GST_ELEMENT(priv->confbin), + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + purple_debug_error("backend-fs2", + "Failed to start conference.\n"); + return FALSE; + } + + return TRUE; +} + +static gboolean purple_media_backend_fs2_add_stream(PurpleMediaBackend *self, const gchar *sess_id, const gchar *who, PurpleMediaSessionType type, gboolean initiator, const gchar *transmitter, guint num_params, GParameter *params) { - return FALSE; + PurpleMediaBackendFs2Private *priv = + PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); + + if (priv->conference == NULL || !_init_conference(self)) { + purple_debug_error("backend-fs2", + "Error initializing the conference.\n"); + return FALSE; + } + + return TRUE; } static void