/pidgin/main: 8959f9825768: Copy audio test from vvconfig into P...

Elliott Sales de Andrade qulogic at pidgin.im
Mon Nov 5 18:15:58 EST 2012


Changeset: 8959f98257682aebbb02ad62ee419e8484c8a708
Author:	 Elliott Sales de Andrade <qulogic at pidgin.im>
Date:	 2012-09-14 01:16 -0400
Branch:	 default
URL: http://hg.pidgin.im/pidgin/main/rev/8959f9825768

Description:

Copy audio test from vvconfig into Preferences window.

The Automatic src/sink doesn't work yet as I'm not sure exactly
what it's doing right now. Also, GtkVolumeButton is 2.12, but I'm
hoping we'll get a dependency bump soon ;)

diffstat:

 pidgin/gtkprefs.c |  243 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 243 insertions(+), 0 deletions(-)

diffs (267 lines):

diff --git a/pidgin/gtkprefs.c b/pidgin/gtkprefs.c
--- a/pidgin/gtkprefs.c
+++ b/pidgin/gtkprefs.c
@@ -2983,6 +2983,14 @@ static const gchar *VIDEO_SINK_PLUGINS[]
 	NULL
 };
 
+typedef struct {
+	GtkWidget *level;
+	GtkWidget *threshold;
+	GtkWidget *volume;
+} BusCbCtx;
+
+static GstElement *pipeline;
+
 static GList *
 get_vv_element_devices(const gchar *element_name)
 {
@@ -3164,6 +3172,240 @@ make_vv_frame(GtkWidget *parent, GtkSize
 	                         G_CALLBACK(purple_prefs_disconnect_by_handle), vbox);
 }
 
+static GstElement *
+create_test_element(const char *type, const char *dir, PurpleMediaElementInfo *info)
+{
+	char *tmp;
+	const gchar *plugin;
+	const gchar *device;
+	GstElement *ret;
+
+	tmp = g_strdup_printf("/plugins/core/vvconfig/%s/%s/plugin", type, dir);
+	plugin = purple_prefs_get_string(tmp);
+	g_free(tmp);
+
+	tmp = g_strdup_printf("/plugins/core/vvconfig/%s/%s/device", type, dir);
+	device = purple_prefs_get_string(tmp);
+	g_free(tmp);
+
+	if (plugin[0] == '\0')
+		return purple_media_element_info_call_create(info, NULL, NULL, NULL);
+
+	ret = gst_element_factory_make(plugin, NULL);
+	if (device[0] != '\0')
+		g_object_set(G_OBJECT(ret), "device", device, NULL);
+
+	return ret;
+}
+
+static GstElement *
+create_pipeline(void)
+{
+	GstElement *pipeline;
+	GstElement *src, *sink;
+	GstElement *volume;
+	GstElement *level;
+	GstElement *valve;
+
+	pipeline = gst_pipeline_new("voicetest");
+	src = create_test_element("audio", "src", NULL/*old_audio_src*/);
+	sink = create_test_element("audio", "sink", NULL/*old_sudio_sink*/);
+	volume = gst_element_factory_make("volume", "volume");
+	level = gst_element_factory_make("level", "level");
+	valve = gst_element_factory_make("valve", "valve");
+
+	gst_bin_add_many(GST_BIN(pipeline), src, volume, level, valve, sink, NULL);
+	gst_element_link_many(src, volume, level, valve, sink, NULL);
+
+	gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
+
+	return pipeline;
+}
+
+static void
+on_volume_change_cb(GtkWidget *w, GstBin *pipeline)
+{
+	GstElement *volume;
+
+	g_return_if_fail(pipeline != NULL);
+
+	volume = gst_bin_get_by_name(pipeline, "volume");
+	g_object_set(volume, "volume",
+	             gtk_scale_button_get_value(GTK_SCALE_BUTTON(w)) * 10.0, NULL);
+}
+
+static gdouble
+gst_msg_db_to_percent(GstMessage *msg, gchar *value_name)
+{
+	const GValue *list;
+	const GValue *value;
+	gdouble value_db;
+	gdouble percent;
+
+	list = gst_structure_get_value(gst_message_get_structure(msg), value_name);
+#if GST_CHECK_VERSION(0,11,0)
+	value = g_value_array_get_nth(g_value_get_boxed(list), 0);
+#else
+	value = gst_value_list_get_value(list, 0);
+#endif
+	value_db = g_value_get_double(value);
+	percent = pow(10, value_db / 20);
+	return (percent > 1.0) ? 1.0 : percent;
+}
+
+static gboolean
+gst_bus_cb(GstBus *bus, GstMessage *msg, BusCbCtx *ctx)
+{
+	if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ELEMENT &&
+		gst_structure_has_name(gst_message_get_structure(msg), "level")) {
+
+		GstElement *src = GST_ELEMENT(GST_MESSAGE_SRC(msg));
+		gchar *name = gst_element_get_name(src);
+
+		if (!strcmp(name, "level")) {
+			gdouble percent;
+			gdouble threshold;
+			GstElement *valve;
+
+			percent = gst_msg_db_to_percent(msg, "rms");
+			gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ctx->level), percent);
+
+			percent = gst_msg_db_to_percent(msg, "decay");
+			threshold = gtk_range_get_value(GTK_RANGE(ctx->threshold)) / 100.0;
+			valve = gst_bin_get_by_name(GST_BIN(GST_ELEMENT_PARENT(src)), "valve");
+			g_object_set(valve, "drop", (percent < threshold), NULL);
+			g_object_set(ctx->level, "text",
+			             (percent < threshold) ? _("DROP") : " ", NULL);
+		}
+
+		g_free(name);
+	}
+
+	return TRUE;
+}
+
+static void
+voice_test_destroy_cb(GtkWidget *w, gpointer data)
+{
+	if (!pipeline)
+		return;
+
+	gst_element_set_state(pipeline, GST_STATE_NULL);
+	gst_object_unref(pipeline);
+	pipeline = NULL;
+}
+
+static void
+toggle_voice_test_cb(GtkToggleButton *test, gpointer data)
+{
+	BusCbCtx *ctx = data;
+	GstBus *bus;
+
+	if (gtk_toggle_button_get_active(test)) {
+		gtk_widget_set_sensitive(ctx->level, TRUE);
+		pipeline = create_pipeline();
+		bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
+		gst_bus_add_signal_watch(bus);
+		g_signal_connect(bus, "message", G_CALLBACK(gst_bus_cb), ctx);
+		gst_object_unref(bus);
+
+		g_signal_connect(ctx->volume, "value-changed",
+		                 G_CALLBACK(on_volume_change_cb), pipeline);
+		g_signal_connect(test, "destroy",
+		                 G_CALLBACK(voice_test_destroy_cb), NULL);
+	} else {
+		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ctx->level), 0.0);
+		gtk_widget_set_sensitive(ctx->level, FALSE);
+		gst_element_set_state(pipeline, GST_STATE_NULL);
+		gst_object_unref(pipeline);
+		g_object_disconnect(ctx->volume, "any-signal::value-changed",
+		                    G_CALLBACK(on_volume_change_cb), pipeline,
+		                    NULL);
+		g_object_disconnect(test, "any-signal::destroy",
+		                    G_CALLBACK(voice_test_destroy_cb), NULL,
+		                    NULL);
+		pipeline = NULL;
+	}
+}
+
+static void
+scale_value_changed_cb(GtkScaleButton *button, gpointer data)
+{
+	const char *pref = data;
+	purple_prefs_set_int(pref,
+	                     gtk_scale_button_get_value(GTK_SCALE_BUTTON(button)) * 100);
+}
+
+static void
+threshold_value_changed_cb(GtkScale *scale, GtkWidget *label)
+{
+	int value;
+	char *tmp;
+
+	value = (int)gtk_range_get_value(GTK_RANGE(scale));
+	tmp = g_strdup_printf(_("Silence threshold: %d%%"), value);
+	gtk_label_set_label(GTK_LABEL(label), tmp);
+	g_free(tmp);
+
+	purple_prefs_set_int("/purple/media/audio/silence_threshold", value);
+}
+
+static void
+make_voice_test(GtkWidget *vbox)
+{
+	GtkWidget *test;
+	GtkWidget *hbox;
+	GtkWidget *label;
+	GtkWidget *level;
+	GtkWidget *volume;
+	GtkWidget *threshold;
+	BusCbCtx *ctx;
+	char *tmp;
+
+	label = gtk_label_new(NULL);
+	gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
+
+	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_CAT_SPACE);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+	label = gtk_label_new(_("Volume:"));
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+	volume = gtk_volume_button_new();
+	gtk_box_pack_start(GTK_BOX(hbox), volume, TRUE, TRUE, 0);
+	gtk_scale_button_set_value(GTK_SCALE_BUTTON(volume),
+			purple_prefs_get_int("/purple/media/audio/volume/input") / 100.0);
+	g_signal_connect(volume, "value-changed",
+	                 G_CALLBACK(scale_value_changed_cb),
+	                 "/purple/media/audio/volume/input");
+
+	tmp = g_strdup_printf(_("Silence threshold: %d%%"),
+	                      purple_prefs_get_int("/purple/media/audio/silence_threshold"));
+	label = gtk_label_new(tmp);
+	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+	gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+	g_free(tmp);
+	threshold = gtk_hscale_new_with_range(0, 100, 1);
+	gtk_box_pack_start(GTK_BOX(vbox), threshold, FALSE, FALSE, 0);
+	gtk_range_set_value(GTK_RANGE(threshold),
+			purple_prefs_get_int("/purple/media/audio/silence_threshold"));
+	gtk_scale_set_draw_value(GTK_SCALE(threshold), FALSE);
+	g_signal_connect(threshold, "value-changed",
+	                 G_CALLBACK(threshold_value_changed_cb), label);
+
+	test = gtk_toggle_button_new_with_label(_("Test Audio"));
+	gtk_box_pack_start(GTK_BOX(vbox), test, FALSE, FALSE, 0);
+
+	level = gtk_progress_bar_new();
+	gtk_box_pack_start(GTK_BOX(vbox), level, FALSE, FALSE, 0);
+	gtk_widget_set_sensitive(level, FALSE);
+
+	ctx = g_new(BusCbCtx, 1);
+	ctx->volume = volume;
+	ctx->level = level;
+	ctx->threshold = threshold;
+	g_signal_connect(test, "toggled",
+	                 G_CALLBACK(toggle_voice_test_cb), ctx);
+}
+
 static GtkWidget *
 vv_page(void)
 {
@@ -3183,6 +3425,7 @@ vv_page(void)
 	make_vv_frame(vbox, sg, _("Output"), AUDIO_SINK_PLUGINS,
 	              "/plugins/core/vvconfig/audio/sink/plugin",
 	              "/plugins/core/vvconfig/audio/sink/device");
+	make_voice_test(vbox);
 
 	vbox = pidgin_make_frame(ret, _("Video"));
 	make_vv_frame(vbox, sg, _("Input"), VIDEO_SRC_PLUGINS,



More information about the Commits mailing list