changeset 23799:6bf2dfb350c0

Fix video plugin/device preference and preview.
author Mike Ruprecht <maiku@soc.pidgin.im>
date Sat, 24 May 2008 20:02:01 +0000
parents 16543025aed1
children 4b9b265a8100
files libpurple/media.c pidgin/gtkprefs.c
diffstat 2 files changed, 145 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/media.c	Sat May 24 01:40:34 2008 +0000
+++ b/libpurple/media.c	Sat May 24 20:02:01 2008 +0000
@@ -546,7 +546,7 @@
 			!GST_IS_PROPERTY_PROBE (element) ||
 			!(probe = GST_PROPERTY_PROBE (element)) ||
 			!(pspec = gst_property_probe_get_property (probe, "device"))) {
-		purple_debug_info("Found source '%s' (%s) - no device",
+		purple_debug_info("media", "Found source '%s' (%s) - no device\n",
 				longname, GST_PLUGIN_FEATURE (factory)->name);
 	} else {
 		gint n;
@@ -571,6 +571,12 @@
 				gst_element_set_state (element, GST_STATE_NULL);
 
 				ret = g_list_append(ret, device);
+
+				name = purple_media_get_device_name(GST_ELEMENT(element), device);
+				purple_debug_info("media", "Found source '%s' (%s) - device '%s' (%s)\n",
+						  longname, GST_PLUGIN_FEATURE (factory)->name,
+						  name, g_value_get_string(device));
+				g_free(name);
 			}
 		}
 	}
--- a/pidgin/gtkprefs.c	Sat May 24 01:40:34 2008 +0000
+++ b/pidgin/gtkprefs.c	Sat May 24 20:02:01 2008 +0000
@@ -1920,9 +1920,9 @@
 	GList *ret = NULL;
 
 	for(; devices ; devices = devices->next) {
-		gchar *name = purple_media_get_device_name(element, devices->data);
+		gchar *name = purple_media_get_device_name(GST_ELEMENT(element), devices->data);
 		ret = g_list_append(ret, name);
-		ret = g_list_append(ret, name);
+		ret = g_list_append(ret, g_value_dup_string(devices->data));
 	}
 
 	return ret;
@@ -1930,36 +1930,132 @@
 
 /*
  * Test functions to run video preview
- * (this is not really functional right now...)
- *
  */
+static gboolean
+preview_video_bus_call(GstBus *bus, GstMessage *msg, gpointer pipeline)
+{
+	switch(GST_MESSAGE_TYPE(msg)) {
+		case GST_MESSAGE_EOS:
+			purple_debug_info("preview-video", "End of Stream\n");
+			break;
+		case GST_MESSAGE_ERROR: {
+			gchar *debug = NULL;
+			GError *err = NULL;
+
+			gst_message_parse_error(msg, &err, &debug);
+
+			purple_debug_error("preview-video", "Error: %s\n", err->message);
+			g_error_free(err);
+
+			if (debug) {
+				purple_debug_error("preview-video", "details: %s\n", debug);
+				g_free (debug);
+			}
+			break;
+		}
+		default:
+			return TRUE;
+	}
+
+	gst_element_set_state(pipeline, GST_STATE_NULL);
+	gst_object_unref(GST_PIPELINE(pipeline));
+	return TRUE;
+}
+
 static void
 preview_button_clicked(GtkWidget *widget, gpointer *data)
 {
-	GstElement *video = (GstElement *) data;
+	const char *plugin = purple_prefs_get_string("/purple/media/video/plugin");
+	const char *device = purple_prefs_get_string("/purple/media/video/device");
+	GstBus *bus;
 
 	/* create a preview window... */
-	GstElement *output = gst_element_factory_make("autovideosink", NULL);
 	GstElement *pipeline = NULL;
 	GError *p_err;
 
-	gchar test_pipeline_str[50] = "v4lsrc ! ffmpegcolorspace ! autovideosink";
+	gchar *test_pipeline_str = NULL;
+
+	if (strlen(device) > 0)
+		test_pipeline_str = g_strdup_printf("%s device=\"%s\" !" \
+						    " ffmpegcolorspace !" \
+						    " autovideosink",
+						    plugin, device);
+	else
+		test_pipeline_str = g_strdup_printf("%s ! ffmpegcolorspace !" \
+						    " autovideosink", plugin);
+
 	pipeline = gst_parse_launch (test_pipeline_str, &p_err);
 
+	g_free(test_pipeline_str);
+
+	bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
+	gst_bus_add_watch(bus, preview_video_bus_call, pipeline);
+	gst_object_unref(bus);
+
 	gst_element_set_state(pipeline, GST_STATE_PLAYING);
 }
 
+static void
+media_plugin_changed_cb(const gchar *name, PurplePrefType type,
+			gconstpointer value, gpointer data)
+{
+	GtkWidget *hbox = data;
+	GtkWidget *dd = NULL;
+	GtkWidget *preview_button = NULL;
+	const char *plugin = value;
+	const char *device = purple_prefs_get_string("/purple/media/video/device");
+	GstElement *video = purple_media_get_element(plugin);
+	GList *video_devices = purple_media_get_devices(video);
+	GList *video_items = get_device_items(video, video_devices);
+	GList *list;
+	g_list_free(video_devices);
+
+	if (video_items == NULL) {
+		video_items = g_list_prepend(video_items, g_strdup(""));
+		video_items = g_list_prepend(video_items, g_strdup("Default"));
+	}
+
+	if (g_list_find(video_items, device) == NULL)
+	{
+		purple_prefs_set_string("/purple/media/video/device", 
+					g_list_next(video_items)->data);
+	}
+
+	list = gtk_container_get_children(GTK_CONTAINER(hbox));
+
+	while (list) {
+		gtk_widget_destroy(list->data);
+		list = g_list_delete_link(list, list);
+	}
+
+	dd = pidgin_prefs_dropdown_from_list(hbox, _("_Device:"), PURPLE_PREF_STRING,
+					     "/purple/media/video/device",
+					     video_items);
+
+	gtk_misc_set_alignment(GTK_MISC(dd), 0, 0.5);
+
+	preview_button = gtk_button_new_with_mnemonic(_("_Preview"));
+	g_signal_connect(G_OBJECT(preview_button), "clicked",
+			 G_CALLBACK(preview_button_clicked), video);
+
+	gtk_container_add(GTK_CONTAINER(hbox), preview_button);
+
+	gtk_widget_show_all(hbox);
+}
+
 static GtkWidget *
 media_page()
 {
 	GtkWidget *ret;
-	GtkWidget *sg;
 	GtkWidget *vbox;
 	GtkWidget *hbox;
 	GtkWidget *dd;
 	GtkWidget *preview_button;
-
-	GstElement *video = purple_media_get_element("v4lsrc");
+	GtkSizeGroup *sg;
+	const char *plugin = purple_prefs_get_string("/purple/media/video/plugin");
+	const char *device = purple_prefs_get_string("/purple/media/video/device");
+
+	GstElement *video = purple_media_get_element(plugin);
 	GstElement *audio = purple_media_get_element("alsasrc");
 
 	GList *video_devices = purple_media_get_devices(video);
@@ -1971,17 +2067,46 @@
 	g_list_free(video_devices);
 	g_list_free(audio_devices);
 
+	if (video_items == NULL) {
+		video_items = g_list_prepend(video_items, "");
+		video_items = g_list_prepend(video_items, "Default");
+	}
+
+	if (g_list_find(video_items, device) == NULL)
+	{
+		purple_prefs_set_string("/purple/media/video/device", 
+					g_list_next(video_items)->data);
+	}
+
 	ret = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE);
 	gtk_container_set_border_width (GTK_CONTAINER (ret), PIDGIN_HIG_BORDER);
 
 	sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
 
 	vbox = pidgin_make_frame (ret, _("Video Input"));
+
+	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
+	dd = pidgin_prefs_dropdown(vbox, _("_Plugin:"), PURPLE_PREF_STRING,
+				   "/purple/media/video/plugin",
+				   _("Default"), "gconfvideosrc",
+				   _("Video4Linux"), "v4lsrc",
+				   _("Video4Linux2"), "v4l2src",
+				   NULL);
+
+	gtk_size_group_add_widget(sg, dd);
+	gtk_misc_set_alignment(GTK_MISC(dd), 0, 0.5);
+
 	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
 	dd = pidgin_prefs_dropdown_from_list(hbox, _("_Device:"), PURPLE_PREF_STRING,
 			"/purple/media/video/device",
 			video_items);
 
+	purple_prefs_connect_callback(prefs, "/purple/media/video/plugin",
+				      media_plugin_changed_cb, hbox);
+
+	g_signal_connect_swapped(hbox, "destroy",
+				 G_CALLBACK(purple_prefs_disconnect_by_handle), hbox);
+
 	gtk_size_group_add_widget(sg, dd);
 	gtk_misc_set_alignment(GTK_MISC(dd), 0, 0.5);
 
@@ -1989,8 +2114,8 @@
 	g_signal_connect(G_OBJECT(preview_button), "clicked",
 			G_CALLBACK(preview_button_clicked), video);
 
-	gtk_container_add(hbox, preview_button);
-	gtk_container_add(vbox, hbox);
+	gtk_container_add(GTK_CONTAINER(hbox), preview_button);
+	gtk_container_add(GTK_CONTAINER(vbox), hbox);
 
 	vbox = pidgin_make_frame (ret, _("Audio Input"));
 	dd = pidgin_prefs_dropdown_from_list(vbox, _("_Device:"), PURPLE_PREF_STRING,
@@ -2266,6 +2391,7 @@
 #ifdef USE_FARSIGHT
 	purple_prefs_add_none("/purple/media");
 	purple_prefs_add_none("/purple/media/video");
+	purple_prefs_add_string("/purple/media/video/plugin", "gconfvideosrc");
 	purple_prefs_add_string("/purple/media/video/device", "");
 	purple_prefs_add_none("/purple/media/audio");
 	purple_prefs_add_string("/purple/media/audio/device", "");