changeset 29149:4aa30863743b

Create and dispose the conference in the Farsight 2 media backend.
author maiku@pidgin.im
date Thu, 22 Oct 2009 23:29:51 +0000
parents af08588c06f5
children c9845a081a3a
files libpurple/media/backend-fs2.c
diffstat 1 files changed, 153 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- 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 <gst/farsight/fs-conference-iface.h>
 
 /** @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