build: fprintf, sprintf, sscanf need stdio.h
[platform/upstream/gstreamer.git] / tests / examples / spectrum / demo-audiotest.c
index ed47278..a4dc1c3 100644 (file)
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+/* TODO: add wave selection */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <math.h>
 #include <gst/gst.h>
 #include <gtk/gtk.h>
 
-#define DEFAULT_AUDIOSINK "alsasink"
-#define SPECT_BANDS 256
+#ifndef DEFAULT_AUDIOSINK
+#define DEFAULT_AUDIOSINK "autoaudiosink"
+#endif
+
+static guint spect_height = 64;
+static guint spect_bands = 256;
+static gfloat height_scale = 1.0;
 
 static GtkWidget *drawingarea = NULL;
+static GstClock *sync_clock = NULL;
 
 static void
 on_window_destroy (GtkObject * object, gpointer user_data)
@@ -48,28 +57,63 @@ on_frequency_changed (GtkRange * range, gpointer user_data)
   g_object_set (machine, "freq", value, NULL);
 }
 
+static gboolean
+on_configure_event (GtkWidget * widget, GdkEventConfigure * event,
+    gpointer user_data)
+{
+  GstElement *spectrum = GST_ELEMENT (user_data);
+
+  /*GST_INFO ("%d x %d", event->width, event->height); */
+  spect_height = event->height;
+  height_scale = event->height / 64.0;
+  spect_bands = event->width;
+
+  g_object_set (G_OBJECT (spectrum), "bands", spect_bands, NULL);
+  return FALSE;
+}
+
 /* draw frequency spectrum as a bunch of bars */
 static void
-draw_spectrum (guchar * data)
+draw_spectrum (gfloat * data)
 {
   gint i;
-  GdkRectangle rect = { 0, 0, SPECT_BANDS, 50 };
+  GdkRectangle rect = { 0, 0, spect_bands, spect_height };
 
   if (!drawingarea)
     return;
 
   gdk_window_begin_paint_rect (drawingarea->window, &rect);
   gdk_draw_rectangle (drawingarea->window, drawingarea->style->black_gc,
-      TRUE, 0, 0, SPECT_BANDS, 50);
-  for (i = 0; i < SPECT_BANDS; i++) {
+      TRUE, 0, 0, spect_bands, spect_height);
+  for (i = 0; i < spect_bands; i++) {
     gdk_draw_rectangle (drawingarea->window, drawingarea->style->white_gc,
-        TRUE, i, 64 - data[i], 1, data[i]);
+        TRUE, i, -data[i], 1, spect_height + data[i]);
   }
   gdk_window_end_paint (drawingarea->window);
 }
 
+/* process delayed message */
+static gboolean
+delayed_idle_spectrum_update (gpointer user_data)
+{
+  draw_spectrum ((gfloat *) user_data);
+  g_free (user_data);
+  return (FALSE);
+}
+
+static gboolean
+delayed_spectrum_update (GstClock * sync_clock, GstClockTime time,
+    GstClockID id, gpointer user_data)
+{
+  if (GST_CLOCK_TIME_IS_VALID (time))
+    g_idle_add (delayed_idle_spectrum_update, user_data);
+  else
+    g_free (user_data);
+  return (TRUE);
+}
+
 /* receive spectral data from element message */
-gboolean
+static gboolean
 message_handler (GstBus * bus, GstMessage * message, gpointer data)
 {
   if (message->type == GST_MESSAGE_ELEMENT) {
@@ -77,17 +121,37 @@ message_handler (GstBus * bus, GstMessage * message, gpointer data)
     const gchar *name = gst_structure_get_name (s);
 
     if (strcmp (name, "spectrum") == 0) {
-      guchar spect[SPECT_BANDS];
-      const GValue *list;
-      const GValue *value;
-      guint i;
-
-      list = gst_structure_get_value (s, "spectrum");
-      for (i = 0; i < SPECT_BANDS; ++i) {
-        value = gst_value_list_get_value (list, i);
-        spect[i] = g_value_get_uchar (value);
+      GstElement *spectrum = GST_ELEMENT (GST_MESSAGE_SRC (message));
+      GstClockTime timestamp, duration;
+      GstClockTime waittime = GST_CLOCK_TIME_NONE;
+
+      if (gst_structure_get_clock_time (s, "running-time", &timestamp) &&
+          gst_structure_get_clock_time (s, "duration", &duration)) {
+        /* wait for middle of buffer */
+        waittime = timestamp + duration / 2;
+      } else if (gst_structure_get_clock_time (s, "endtime", &timestamp)) {
+        waittime = timestamp;
+      }
+      if (GST_CLOCK_TIME_IS_VALID (waittime)) {
+        GstClockID clock_id;
+        GstClockTime basetime = gst_element_get_base_time (spectrum);
+        gfloat *spect = g_new (gfloat, spect_bands);
+        const GValue *list;
+        const GValue *value;
+        guint i;
+
+        list = gst_structure_get_value (s, "magnitude");
+        for (i = 0; i < spect_bands; ++i) {
+          value = gst_value_list_get_value (list, i);
+          spect[i] = height_scale * g_value_get_float (value);
+        }
+
+        clock_id =
+            gst_clock_new_single_shot_id (sync_clock, waittime + basetime);
+        gst_clock_id_wait_async (clock_id, delayed_spectrum_update,
+            (gpointer) spect);
+        gst_clock_id_unref (clock_id);
       }
-      draw_spectrum (spect);
     }
   }
   return TRUE;
@@ -97,7 +161,7 @@ int
 main (int argc, char *argv[])
 {
   GstElement *bin;
-  GstElement *src, *spectrum, *sink;
+  GstElement *src, *spectrum, *audioconvert, *sink;
   GstBus *bus;
   GtkWidget *appwindow, *vbox, *widget;
 
@@ -107,19 +171,19 @@ main (int argc, char *argv[])
   bin = gst_pipeline_new ("bin");
 
   src = gst_element_factory_make ("audiotestsrc", "src");
-  /*
-     g_object_set (G_OBJECT (src), "wave", 0, NULL);
-   */
+  g_object_set (G_OBJECT (src), "wave", 0, NULL);
 
   spectrum = gst_element_factory_make ("spectrum", "spectrum");
-  g_object_set (G_OBJECT (spectrum), "bands", SPECT_BANDS, "threshold", -80,
+  g_object_set (G_OBJECT (spectrum), "bands", spect_bands, "threshold", -80,
       "message", TRUE, NULL);
 
+  audioconvert = gst_element_factory_make ("audioconvert", "audioconvert");
+
   sink = gst_element_factory_make (DEFAULT_AUDIOSINK, "sink");
 
-  gst_bin_add_many (GST_BIN (bin), src, spectrum, sink, NULL);
-  if (!gst_element_link_many (src, spectrum, sink, NULL)) {
-    fprintf (stderr, "cant link elements\n");
+  gst_bin_add_many (GST_BIN (bin), src, spectrum, audioconvert, sink, NULL);
+  if (!gst_element_link_many (src, spectrum, audioconvert, sink, NULL)) {
+    fprintf (stderr, "can't link elements\n");
     exit (1);
   }
 
@@ -127,6 +191,8 @@ main (int argc, char *argv[])
   gst_bus_add_watch (bus, message_handler, NULL);
   gst_object_unref (bus);
 
+  sync_clock = gst_pipeline_get_clock (GST_PIPELINE (bin));
+
   appwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   g_signal_connect (G_OBJECT (appwindow), "destroy",
       G_CALLBACK (on_window_destroy), NULL);
@@ -138,11 +204,13 @@ main (int argc, char *argv[])
   gtk_range_set_value (GTK_RANGE (widget), 440.0);
   g_signal_connect (G_OBJECT (widget), "value-changed",
       G_CALLBACK (on_frequency_changed), (gpointer) src);
-  gtk_container_add (GTK_CONTAINER (vbox), widget);
+  gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
 
   drawingarea = gtk_drawing_area_new ();
-  gtk_widget_set_size_request (drawingarea, SPECT_BANDS, 64);
-  gtk_container_add (GTK_CONTAINER (vbox), drawingarea);
+  gtk_widget_set_size_request (drawingarea, spect_bands, spect_height);
+  g_signal_connect (G_OBJECT (drawingarea), "configure-event",
+      G_CALLBACK (on_configure_event), (gpointer) spectrum);
+  gtk_box_pack_start (GTK_BOX (vbox), drawingarea, TRUE, TRUE, 0);
 
   gtk_container_add (GTK_CONTAINER (appwindow), vbox);
   gtk_widget_show_all (appwindow);
@@ -151,6 +219,7 @@ main (int argc, char *argv[])
   gtk_main ();
   gst_element_set_state (bin, GST_STATE_NULL);
 
+  gst_object_unref (sync_clock);
   gst_object_unref (bin);
 
   return 0;