Merge branch 'master' into 0.11
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 27 Oct 2011 13:44:58 +0000 (15:44 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Thu, 27 Oct 2011 13:44:58 +0000 (15:44 +0200)
Conflicts:
configure.ac
gst-libs/gst/audio/gstbaseaudiosink.c
gst/audioconvert/channelmixtest.c
gst/playback/gstplaybasebin.c
gst/playback/gstsubtitleoverlay.c
tests/examples/Makefile.am
tests/examples/audio/Makefile.am

20 files changed:
Android.mk
Makefile.am
ext/ogg/gstoggdemux.c
ext/vorbis/gstvorbisdec.c
gst-libs/gst/audio/gstaudiodecoder.c
gst-libs/gst/audio/gstbaseaudiosink.c
gst/audioconvert/Makefile.am
gst/audioconvert/channelmixtest.c [deleted file]
gst/playback/gstdecodebin2.c
gst/playback/gstplaysinkaudioconvert.c
gst/playback/gstsubtitleoverlay.c
sys/ximage/ximagesink.c
sys/xvimage/xvimagesink.c
tests/examples/Makefile.am
tests/examples/audio/.gitignore
tests/examples/audio/Makefile.am
tests/examples/audio/audiomix.c [new file with mode: 0644]
tests/examples/audio/volume.c [moved from tests/examples/volume/volume.c with 98% similarity]
tests/examples/volume/.gitignore [deleted file]
tests/examples/volume/Makefile.am [deleted file]

index 4bfbe75..f9f4cef 100644 (file)
@@ -61,9 +61,12 @@ GST_PLUGINS_BASE_BUILT_SOURCES :=                                            \
        gst/audiorate/Android.mk                                        \
        gst/volume/Android.mk                                   \
        tools/Android.mk                                        \
-       ext/vorbis/Android.mk                           \
        ext/ogg/Android.mk
 
+ifneq ($(NDK_BUILD), true)
+GST_PLUGINS_BASE_BUILT_SOURCES += ext/vorbis/Android.mk
+endif
+
 GST_PLUGINS_BASE_BUILT_SOURCES := $(patsubst %, $(abspath $(GST_PLUGINS_BASE_TOP))/%, $(GST_PLUGINS_BASE_BUILT_SOURCES))
 
 
@@ -119,5 +122,7 @@ CONFIGURE_TARGETS += gst-plugins-base-configure
 -include $(GST_PLUGINS_BASE_TOP)/gst/audiorate/Android.mk
 -include $(GST_PLUGINS_BASE_TOP)/gst/volume/Android.mk
 -include $(GST_PLUGINS_BASE_TOP)/ext/ogg/Android.mk
+ifneq ($(NDK_BUILD), true)
 -include $(GST_PLUGINS_BASE_TOP)/ext/vorbis/Android.mk
+endif
 -include $(GST_PLUGINS_BASE_TOP)/tools/Android.mk
index 126379f..0f329cb 100644 (file)
@@ -77,6 +77,7 @@ CRUFT_FILES = \
        $(top_builddir)/common/shave \
        $(top_builddir)/common/shave-libtool \
        $(top_builddir)/gst-libs/gst/audio/testchannels \
+       $(top_builddir)/tests/examples/volume/volume \
        $(top_builddir)/tools/gst-discoverer
 
 CRUFT_DIRS = \
index a95397c..74703c5 100644 (file)
@@ -1697,7 +1697,9 @@ gst_ogg_chain_new_stream (GstOggChain * chain, guint32 serialno)
   GST_DEBUG_OBJECT (chain->ogg,
       "creating new stream %08x in chain %p", serialno, chain);
 
-  ret = g_object_new (GST_TYPE_OGG_PAD, NULL);
+  name = g_strdup_printf ("serial_%08x", serialno);
+  ret = g_object_new (GST_TYPE_OGG_PAD, "name", name, NULL);
+  g_free (name);
   /* we own this one */
   gst_object_ref_sink (ret);
 
@@ -1711,10 +1713,6 @@ gst_ogg_chain_new_stream (GstOggChain * chain, guint32 serialno)
   if (ogg_stream_init (&ret->map.stream, serialno) != 0)
     goto init_failed;
 
-  name = g_strdup_printf ("serial_%08x", serialno);
-  gst_object_set_name (GST_OBJECT (ret), name);
-  g_free (name);
-
   /* FIXME: either do something with it or remove it */
   list = gst_tag_list_new ();
   gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_SERIAL, serialno,
@@ -3077,6 +3075,7 @@ gst_ogg_demux_get_duration_push (GstOggDemux * ogg, int flags)
   } else {
     GST_INFO_OBJECT (ogg, "Seek failed, duration will stay unknown");
     ogg->push_state = PUSH_PLAYING;
+    ogg->push_disable_seeking = TRUE;
     return FALSE;
   }
 }
index 7b1b62d..45f0dc8 100644 (file)
@@ -428,9 +428,6 @@ vorbis_handle_header_packet (GstVorbisDec * vd, ogg_packet * packet)
       break;
   }
 
-  /* consumer header packet/frame */
-  gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (vd), NULL, 1);
-
   return res;
 
   /* ERRORS */
@@ -482,7 +479,7 @@ vorbis_dec_handle_header_caps (GstVorbisDec * vd)
     GstBuffer *buf = NULL;
     gint i = 0;
 
-    while (result == GST_FLOW_OK) {
+    while (result == GST_FLOW_OK && i < gst_value_array_get_size (array)) {
       value = gst_value_array_get_value (array, i);
       buf = gst_value_get_buffer (value);
       if (!buf)
@@ -668,6 +665,8 @@ vorbis_dec_handle_frame (GstAudioDecoder * dec, GstBuffer * buffer)
       goto done;
     }
     result = vorbis_handle_header_packet (vd, packet);
+    /* consumer header packet/frame */
+    gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (vd), NULL, 1);
   } else {
     GstClockTime timestamp, duration;
 
index 72c55c8..93e8fb0 100644 (file)
@@ -1031,7 +1031,7 @@ gst_audio_decoder_drain (GstAudioDecoder * dec)
 {
   GstFlowReturn ret;
 
-  if (dec->priv->drained)
+  if (dec->priv->drained && !dec->priv->gather)
     return GST_FLOW_OK;
   else {
     /* dispatch reverse pending buffers */
index deeb8a0..f8d2655 100644 (file)
@@ -1335,8 +1335,11 @@ gst_base_audio_sink_get_alignment (GstBaseAudioSink * sink,
         "align with prev sample, ABS (%" G_GINT64_FORMAT ") < %"
         G_GINT64_FORMAT, align, maxdrift);
   } else {
+    gint64 diff_s G_GNUC_UNUSED;
+
     /* calculate sample diff in seconds for error message */
-    gint64 diff_s = gst_util_uint64_scale_int (diff, GST_SECOND, rate);
+    diff_s = gst_util_uint64_scale_int (diff, GST_SECOND, rate);
+
     /* timestamps drifted apart from previous samples too much, we need to
      * resync. We log this as an element warning. */
     GST_WARNING_OBJECT (sink,
index b8849b6..1626479 100644 (file)
@@ -26,15 +26,6 @@ noinst_HEADERS = \
        gstfastrandom.h \
        plugin.h
 
-#TESTS = channelmixtest
-#noinst_PROGRAMS = channelmixtest
-
-#channelmixtest_CFLAGS = $(GST_CFLAGS)
-#channelmixtest_LDADD = libgstaudioconvert.la \
-#      $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \
-#      $(GST_LIBS)
-
-
 Android.mk: Makefile.am $(BUILT_SOURCES)
        androgenizer \
        -:PROJECT libgstaudioconvert -:SHARED libgstaudioconvert \
diff --git a/gst/audioconvert/channelmixtest.c b/gst/audioconvert/channelmixtest.c
deleted file mode 100644 (file)
index 595a139..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Benjamin Otte <otte@gnome.org>
- *
- * channelmixtest.c: simple test of channel mixing
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstchannelmix.h"
-#include "plugin.h"
-
-int
-main (gint argc, gchar ** argv)
-{
-  GstElement *bin, *src, *sink;
-  GstAudioConvert *c;
-  GstCaps *caps;
-  guint i, j, k;
-  struct
-  {
-    gchar *sinkcaps;
-    gchar *srccaps;
-    gfloat matrix[6][6];        /* use a predefined matrix here, makes stuff simpler */
-  } tests[] = {
-    /* stereo => mono */
-    {
-      "audio/x-raw, channels=2", "audio/x-raw, channels=1", { {
-      0.5,}, {
-    0.5,},}},
-        /* mono => stereo */
-    {
-      "audio/x-raw, channels=1", "audio/x-raw, channels=2", { {
-    1, 1,},}}
-  };
-
-  gst_init (&argc, &argv);
-
-  for (i = 0; i < G_N_ELEMENTS (tests); i++) {
-    g_print ("running test %u\n", i);
-    bin = gst_element_factory_make ("pipeline", NULL);
-    c = g_object_new (GST_TYPE_AUDIO_CONVERT, NULL);
-    /* avoid gst being braindead */
-    gst_object_set_name (GST_OBJECT (c), "shuddup");
-    src = gst_element_factory_make ("fakesrc", NULL);
-    sink = gst_element_factory_make ("fakesink", NULL);
-    gst_bin_add_many (GST_BIN (bin), src, c, sink, NULL);
-    caps = gst_caps_from_string (tests[i].sinkcaps);
-    g_assert (caps);
-    if (!gst_element_link_filtered (src, GST_ELEMENT (c), caps))
-      g_assert_not_reached ();
-    gst_caps_unref (caps);
-    caps = gst_caps_from_string (tests[i].srccaps);
-    g_assert (caps);
-    if (!gst_element_link_filtered (GST_ELEMENT (c), sink, caps))
-      g_assert_not_reached ();
-    gst_caps_unref (caps);
-    if (!gst_element_set_state (bin, GST_STATE_PLAYING))
-      g_assert_not_reached ();
-    g_assert (c->srccaps.channels <= 6);
-    g_assert (c->sinkcaps.channels <= 6);
-    for (j = 0; j < 6; j++) {
-      for (k = 0; k < 6; k++) {
-        if (j < c->sinkcaps.channels && k < c->srccaps.channels) {
-          if (tests[i].matrix[j][k] != c->matrix[j][k]) {
-            g_printerr ("matrix[j][k] should be %g but is %g\n",
-                tests[i].matrix[j][k], c->matrix[j][k]);
-            g_assert_not_reached ();
-          }
-        } else {
-          g_assert (tests[i].matrix[j][k] == 0);
-        }
-      }
-    }
-    gst_object_unref (bin);
-  }
-
-  return 0;
-}
index 840c223..98e0e97 100644 (file)
@@ -174,6 +174,8 @@ struct _GstDecodeBin
   gboolean expose_allstreams;   /* Whether to expose unknow type streams or not */
 
   gboolean upstream_seekable;   /* if upstream is seekable */
+
+  GList *filtered;              /* elements for which error messages are filtered */
 };
 
 struct _GstDecodeBinClass
@@ -289,6 +291,7 @@ static void caps_notify_cb (GstPad * pad, GParamSpec * unused,
 static GstPad *find_sink_pad (GstElement * element);
 static GstStateChangeReturn gst_decode_bin_change_state (GstElement * element,
     GstStateChange transition);
+static void gst_decode_bin_handle_message (GstBin * bin, GstMessage * message);
 
 #define EXPOSE_LOCK(dbin) G_STMT_START {                               \
     GST_LOG_OBJECT (dbin,                                              \
@@ -584,9 +587,11 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
 {
   GObjectClass *gobject_klass;
   GstElementClass *gstelement_klass;
+  GstBinClass *gstbin_klass;
 
   gobject_klass = (GObjectClass *) klass;
   gstelement_klass = (GstElementClass *) klass;
+  gstbin_klass = (GstBinClass *) klass;
 
   parent_class = g_type_class_peek_parent (klass);
 
@@ -898,6 +903,9 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
 
   gstelement_klass->change_state =
       GST_DEBUG_FUNCPTR (gst_decode_bin_change_state);
+
+  gstbin_klass->handle_message =
+      GST_DEBUG_FUNCPTR (gst_decode_bin_handle_message);
 }
 
 /* Must be called with factories lock! */
@@ -1692,6 +1700,21 @@ setup_caps_delay:
   }
 }
 
+static void
+add_error_filter (GstDecodeBin * dbin, GstElement * element)
+{
+  GST_OBJECT_LOCK (dbin);
+  dbin->filtered = g_list_prepend (dbin->filtered, element);
+  GST_OBJECT_UNLOCK (dbin);
+}
+
+static void
+remove_error_filter (GstDecodeBin * dbin, GstElement * element)
+{
+  GST_OBJECT_LOCK (dbin);
+  dbin->filtered = g_list_remove (dbin->filtered, element);
+  GST_OBJECT_UNLOCK (dbin);
+}
 
 /* connect_pad:
  *
@@ -1856,45 +1879,52 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
       continue;
     }
 
-    /* ... activate it ... We do this before adding it to the bin so that we
-     * don't accidentally make it post error messages that will stop
-     * everything. */
-    if ((gst_element_set_state (element,
-                GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
-      GST_WARNING_OBJECT (dbin, "Couldn't set %s to READY",
+    /* Filter errors, this will prevent the element from causing the pipeline
+     * to error while we test it using READY state. */
+    add_error_filter (dbin, element);
+
+    /* ... add it ... */
+    if (!(gst_bin_add (GST_BIN_CAST (dbin), element))) {
+      GST_WARNING_OBJECT (dbin, "Couldn't add %s to the bin",
           GST_ELEMENT_NAME (element));
+      remove_error_filter (dbin, element);
       gst_object_unref (element);
       continue;
     }
 
-    /* 2.3. Find its sink pad, this should work after activating it. */
+    /* Find its sink pad. */
     if (!(sinkpad = find_sink_pad (element))) {
       GST_WARNING_OBJECT (dbin, "Element %s doesn't have a sink pad",
           GST_ELEMENT_NAME (element));
-      gst_element_set_state (element, GST_STATE_NULL);
-      gst_object_unref (element);
+      remove_error_filter (dbin, element);
+      gst_bin_remove (GST_BIN (dbin), element);
       continue;
     }
 
-    /* 2.4 add it ... */
-    if (!(gst_bin_add (GST_BIN_CAST (dbin), element))) {
-      GST_WARNING_OBJECT (dbin, "Couldn't add %s to the bin",
-          GST_ELEMENT_NAME (element));
+    /* ... and try to link */
+    if ((gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) {
+      GST_WARNING_OBJECT (dbin, "Link failed on pad %s:%s",
+          GST_DEBUG_PAD_NAME (sinkpad));
+      remove_error_filter (dbin, element);
       gst_object_unref (sinkpad);
-      gst_element_set_state (element, GST_STATE_NULL);
-      gst_object_unref (element);
+      gst_bin_remove (GST_BIN (dbin), element);
       continue;
     }
 
-    /* 2.5 ...and try to link */
-    if ((gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) {
-      GST_WARNING_OBJECT (dbin, "Link failed on pad %s:%s",
-          GST_DEBUG_PAD_NAME (sinkpad));
-      gst_element_set_state (element, GST_STATE_NULL);
+    /* ... activate it ... */
+    if ((gst_element_set_state (element,
+                GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
+      GST_WARNING_OBJECT (dbin, "Couldn't set %s to READY",
+          GST_ELEMENT_NAME (element));
+      remove_error_filter (dbin, element);
       gst_object_unref (sinkpad);
       gst_bin_remove (GST_BIN (dbin), element);
       continue;
     }
+
+    /* Stop filtering errors. */
+    remove_error_filter (dbin, element);
+
     gst_object_unref (sinkpad);
     GST_LOG_OBJECT (dbin, "linked on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
 
@@ -3162,6 +3192,9 @@ beach:
   GST_DEBUG ("Chain %p (handled:%d, last_group:%d, drained:%d, switched:%d)",
       chain, handled, *last_group, *drained, *switched);
 
+  if (*drained)
+    g_signal_emit (dbin, gst_decode_bin_signals[SIGNAL_DRAINED], 0, NULL);
+
   return handled;
 }
 
@@ -4003,6 +4036,24 @@ activate_failed:
   }
 }
 
+static void
+gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg)
+{
+  GstDecodeBin *dbin = GST_DECODE_BIN (bin);
+  gboolean drop = FALSE;
+
+  if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
+    GST_OBJECT_LOCK (dbin);
+    drop = (g_list_find (dbin->filtered, GST_MESSAGE_SRC (msg)) != NULL);
+    GST_OBJECT_UNLOCK (dbin);
+  }
+
+  if (drop)
+    gst_message_unref (msg);
+  else
+    GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
+}
+
 gboolean
 gst_decode_bin_plugin_init (GstPlugin * plugin)
 {
index f84c5ab..cfdd7ef 100644 (file)
@@ -336,13 +336,18 @@ gst_play_sink_audio_convert_getcaps (GstPad * pad, GstCaps * filter)
   GstPlaySinkAudioConvert *self =
       GST_PLAY_SINK_AUDIO_CONVERT (gst_pad_get_parent (pad));
   GstCaps *ret;
-  GstPad *otherpad, *peer;
+  GstPad *otherpad, *peer = NULL;
 
   GST_PLAY_SINK_AUDIO_CONVERT_LOCK (self);
   otherpad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (pad));
   GST_PLAY_SINK_AUDIO_CONVERT_UNLOCK (self);
 
-  peer = gst_pad_get_peer (otherpad);
+  if (otherpad) {
+    peer = gst_pad_get_peer (otherpad);
+    gst_object_unref (otherpad);
+    otherpad = NULL;
+  }
+
   if (peer) {
     ret = gst_pad_get_caps (peer, filter);
     gst_object_unref (peer);
@@ -350,7 +355,6 @@ gst_play_sink_audio_convert_getcaps (GstPad * pad, GstCaps * filter)
     ret = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
   }
 
-  gst_object_unref (otherpad);
   gst_object_unref (self);
 
   return ret;
index 5744fc0..0cb7213 100644 (file)
@@ -122,8 +122,7 @@ block_video (GstSubtitleOverlay * self)
   if (self->video_block_pad) {
     self->video_block_id =
         gst_pad_add_probe (self->video_block_pad, GST_PROBE_TYPE_BLOCK,
-        _pad_blocked_cb, gst_object_ref (self),
-        (GDestroyNotify) gst_object_unref);
+        _pad_blocked_cb, self, NULL);
   }
 }
 
@@ -146,8 +145,7 @@ block_subtitle (GstSubtitleOverlay * self)
   if (self->subtitle_block_pad) {
     self->subtitle_block_id =
         gst_pad_add_probe (self->subtitle_block_pad, GST_PROBE_TYPE_BLOCK,
-        _pad_blocked_cb, gst_object_ref (self),
-        (GDestroyNotify) gst_object_unref);
+        _pad_blocked_cb, self, NULL);
   }
 }
 
@@ -805,7 +803,6 @@ _pad_blocked_cb (GstPad * pad, GstProbeType type, gpointer type_data,
       /* Unblock pads */
       unblock_video (self);
       unblock_subtitle (self);
-
       goto out;
     } else if (target) {
       gst_object_unref (target);
@@ -2059,6 +2056,7 @@ gst_subtitle_overlay_init (GstSubtitleOverlay * self)
 
   templ = gst_static_pad_template_get (&srctemplate);
   self->srcpad = gst_ghost_pad_new_no_target_from_template ("src", templ);
+  gst_object_unref (templ);
 
   proxypad =
       GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD (self->srcpad)));
@@ -2073,6 +2071,7 @@ gst_subtitle_overlay_init (GstSubtitleOverlay * self)
   templ = gst_static_pad_template_get (&video_sinktemplate);
   self->video_sinkpad =
       gst_ghost_pad_new_no_target_from_template ("video_sink", templ);
+  gst_object_unref (templ);
   gst_pad_set_event_function (self->video_sinkpad,
       GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_event));
   gst_pad_set_chain_function (self->video_sinkpad,
@@ -2082,12 +2081,13 @@ gst_subtitle_overlay_init (GstSubtitleOverlay * self)
       GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
           (self->video_sinkpad)));
   self->video_block_pad = proxypad;
-
+  gst_object_unref (proxypad);
   gst_element_add_pad (GST_ELEMENT_CAST (self), self->video_sinkpad);
 
   templ = gst_static_pad_template_get (&subtitle_sinktemplate);
   self->subtitle_sinkpad =
       gst_ghost_pad_new_no_target_from_template ("subtitle_sink", templ);
+  gst_object_unref (templ);
   gst_pad_set_link_function (self->subtitle_sinkpad,
       GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_link));
   gst_pad_set_unlink_function (self->subtitle_sinkpad,
@@ -2105,6 +2105,7 @@ gst_subtitle_overlay_init (GstSubtitleOverlay * self)
       GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
           (self->subtitle_sinkpad)));
   self->subtitle_block_pad = proxypad;
+  gst_object_unref (proxypad);
 
   gst_element_add_pad (GST_ELEMENT_CAST (self), self->subtitle_sinkpad);
 
index 59ffe34..dd6bd17 100644 (file)
@@ -1920,8 +1920,9 @@ gst_ximagesink_class_init (GstXImageSinkClass * klass)
       g_param_spec_string ("display", "Display", "X Display name",
           NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS,
-      g_param_spec_boolean ("synchronous", "Synchronous", "When enabled, runs "
-          "the X display in synchronous mode. (used only for debugging)", FALSE,
+      g_param_spec_boolean ("synchronous", "Synchronous",
+          "When enabled, runs the X display in synchronous mode. "
+          "(unrelated to A/V sync, used only for debugging)", FALSE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
       g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
index 244802f..167ac75 100644 (file)
@@ -2826,8 +2826,8 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS,
       g_param_spec_boolean ("synchronous", "Synchronous",
-          "When enabled, runs "
-          "the X display in synchronous mode. (used only for debugging)", FALSE,
+          "When enabled, runs the X display in synchronous mode. "
+          "(unrelated to A/V sync, used only for debugging)", FALSE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
       g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
index 317f851..5025dc8 100644 (file)
@@ -8,8 +8,9 @@ if USE_GIO
 GIO_SUBDIRS = gio
 endif
 
-SUBDIRS = app audio dynamic $(FT2_SUBDIRS) $(GIO_SUBDIRS) overlay playrec volume encoding
+SUBDIRS = app audio dynamic $(FT2_SUBDIRS) $(GIO_SUBDIRS) overlay playrec encoding
 
-DIST_SUBDIRS = app audio dynamic gio overlay seek snapshot playrec volume encoding
+DIST_SUBDIRS = app audio dynamic gio overlay seek snapshot playrec encoding
 
 include $(top_srcdir)/common/parallel-subdirs.mak
+
index 49d7266..8da3b3a 100644 (file)
@@ -1,6 +1,21 @@
+if HAVE_GTK
+GTK_EXAMPLES = audiomix volume
+else
+GTK_EXAMPLES =
+endif
+
+noinst_PROGRAMS = testchannels $(GTK_EXAMPLES)
 
-noinst_PROGRAMS = testchannels
 testchannels_SOURCES = testchannels.c
 testchannels_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
 testchannels_LDADD = $(top_builddir)/gst-libs/gst/audio/libgstaudio-$(GST_MAJORMINOR).la \
                      $(GST_LIBS)
+if HAVE_GTK
+audiomix_SOURCES = audiomix.c
+audiomix_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) -D_GNU_SOURCE
+audiomix_LDADD = $(GST_LIBS) $(GTK_LIBS) $(LIBM)
+
+volume_SOURCES = volume.c
+volume_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) -D_GNU_SOURCE
+volume_LDADD = $(GST_LIBS) $(GTK_LIBS) $(LIBM)
+endif
diff --git a/tests/examples/audio/audiomix.c b/tests/examples/audio/audiomix.c
new file mode 100644 (file)
index 0000000..937f4db
--- /dev/null
@@ -0,0 +1,210 @@
+/* GStreamer
+ *
+ * audiomix.c: sample audio mixing application
+ *
+ * Copyright (C) 2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <gst/gst.h>
+#include <gtk/gtk.h>
+
+/* global items for the interaction */
+static GtkWidget *scale;
+static GObject *volumes[2];
+static gint num_vol = 0;
+
+
+static void
+value_changed_callback (GtkWidget * widget, gpointer * user_data)
+{
+  gdouble value = gtk_range_get_value (GTK_RANGE (widget));
+  g_object_set (volumes[0], "volume", 1.0 - value, NULL);
+  g_object_set (volumes[1], "volume", value, NULL);
+}
+
+static void
+setup_gui (GstElement * volume, gchar * file_name1, gchar * file_name2)
+{
+  GtkWidget *window, *layout, *label;
+  gchar *name, *ext;
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), "audiomix");
+  g_signal_connect (window, "destroy", gtk_main_quit, NULL);
+
+  layout = gtk_table_new (2, 3, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (layout), 6);
+  gtk_container_add (GTK_CONTAINER (window), layout);
+
+  /* channel labels */
+  name = g_path_get_basename (file_name1);
+  if ((ext = strrchr (name, '.')))
+    *ext = '\0';
+  label = gtk_label_new (name);
+  g_free (name);
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (layout), label, 0, 1, 0, 1);
+
+  gtk_table_attach_defaults (GTK_TABLE (layout), gtk_label_new ("|"), 1, 2, 0,
+      1);
+
+  name = g_path_get_basename (file_name2);
+  if ((ext = strrchr (name, '.')))
+    *ext = '\0';
+  label = gtk_label_new (name);
+  g_free (name);
+  gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+  gtk_table_attach_defaults (GTK_TABLE (layout), label, 2, 3, 0, 1);
+
+  /* mix slider */
+  scale = gtk_hscale_new_with_range (0.0, 1.0, 1.0 / 200.0);
+  gtk_range_set_value (GTK_RANGE (scale), 0.0);
+  gtk_widget_set_size_request (scale, 200, -1);
+  gtk_table_attach_defaults (GTK_TABLE (layout), scale, 0, 3, 1, 2);
+  g_signal_connect (scale, "value-changed",
+      G_CALLBACK (value_changed_callback), volume);
+
+  gtk_widget_show_all (GTK_WIDGET (window));
+}
+
+static void
+message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
+{
+  const GstStructure *s;
+
+  s = gst_message_get_structure (message);
+  g_print ("message from \"%s\" (%s): ",
+      GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))),
+      gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
+  if (s) {
+    gchar *sstr;
+
+    sstr = gst_structure_to_string (s);
+    g_print ("%s\n", sstr);
+    g_free (sstr);
+  } else {
+    g_print ("no message details\n");
+  }
+}
+
+static void
+eos_message_received (GstBus * bus, GstMessage * message,
+    GstPipeline * pipeline)
+{
+  message_received (bus, message, pipeline);
+  gtk_main_quit ();
+}
+
+static void
+dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer user_data)
+{
+  GstPad *target = GST_PAD (user_data);
+
+  gst_pad_link (newpad, target);
+  gst_object_unref (target);
+}
+
+static void
+make_mixer_channel (GstElement * pipeline, GstElement * mix, gchar * file_name)
+{
+  GstElement *filesrc, *decodebin, *volume, *convert, *format;
+  GstCaps *caps;
+
+  /* prepare mixer channel */
+  filesrc = gst_element_factory_make ("filesrc", NULL);
+  decodebin = gst_element_factory_make ("decodebin2", NULL);
+  volume = gst_element_factory_make ("volume", NULL);
+  convert = gst_element_factory_make ("audioconvert", NULL);
+  format = gst_element_factory_make ("capsfilter", NULL);
+  gst_bin_add_many (GST_BIN (pipeline), filesrc, decodebin, volume, convert,
+      format, NULL);
+  gst_element_link (filesrc, decodebin);
+  gst_element_link_many (volume, convert, format, mix, NULL);
+
+  /* configure elements */
+  g_object_set (filesrc, "location", file_name, NULL);
+  g_object_set (volume, "volume", (num_vol == 0) ? 1.0 : 0.0, NULL);
+
+  caps = gst_caps_from_string ("audio/x-raw-int, "
+      "channels = (int) 2, "
+      "endianness = (int) BYTE_ORDER, "
+      "width = (int) 16, " "depth = (int) 16, " "signed = (boolean) true");
+  g_object_set (format, "caps", caps, NULL);
+  gst_caps_unref (caps);
+
+  /* remember volume element */
+  volumes[num_vol++] = (GObject *) volume;
+
+  /* handle dynamic pads */
+  g_signal_connect (G_OBJECT (decodebin), "pad-added",
+      G_CALLBACK (dynamic_link), gst_element_get_static_pad (volume, "sink"));
+}
+
+int
+main (int argc, char *argv[])
+{
+  GstElement *pipeline = NULL;
+  GstElement *mix, *convert, *sink;
+  GstBus *bus;
+
+  if (argc < 3) {
+    g_print ("Usage: audiomix <file1> <file2>\n");
+    return 1;
+  }
+
+  gst_init (&argc, &argv);
+  gtk_init (&argc, &argv);
+
+  /* prepare tail of pipeline */
+  pipeline = gst_pipeline_new ("audiomix");
+  mix = gst_element_factory_make ("adder", NULL);
+  convert = gst_element_factory_make ("audioconvert", NULL);
+  sink = gst_element_factory_make ("autoaudiosink", NULL);
+  gst_bin_add_many (GST_BIN (pipeline), mix, convert, sink, NULL);
+  gst_element_link_many (mix, convert, sink, NULL);
+
+  /* prepare mixer channel strips */
+  make_mixer_channel (pipeline, mix, argv[1]);
+  make_mixer_channel (pipeline, mix, argv[2]);
+
+  /* setup message handling */
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
+  g_signal_connect (bus, "message::error", (GCallback) message_received,
+      pipeline);
+  g_signal_connect (bus, "message::warning", (GCallback) message_received,
+      pipeline);
+  g_signal_connect (bus, "message::eos", (GCallback) eos_message_received,
+      pipeline);
+
+  /* setup GUI */
+  setup_gui (pipeline, argv[1], argv[2]);
+
+  /* go to main loop */
+  gst_element_set_state (pipeline, GST_STATE_PLAYING);
+  gtk_main ();
+  gst_element_set_state (pipeline, GST_STATE_NULL);
+  gst_object_unref (pipeline);
+
+  return 0;
+}
similarity index 98%
rename from tests/examples/volume/volume.c
rename to tests/examples/audio/volume.c
index 59e4981..d5bf9ed 100644 (file)
@@ -30,8 +30,8 @@
 #include <gtk/gtk.h>
 
 /* global pointer for the scale widget */
-GtkWidget *elapsed;
-GtkWidget *scale;
+static GtkWidget *elapsed;
+static GtkWidget *scale;
 
 #ifndef M_LN10
 #define M_LN10 (log(10.0))
diff --git a/tests/examples/volume/.gitignore b/tests/examples/volume/.gitignore
deleted file mode 100644 (file)
index 4833bbb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-volume
diff --git a/tests/examples/volume/Makefile.am b/tests/examples/volume/Makefile.am
deleted file mode 100644 (file)
index 7b2f067..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-if HAVE_GTK
-noinst_PROGRAMS = volume
-volume_SOURCES = volume.c
-volume_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) -D_GNU_SOURCE
-volume_LDADD = $(GST_LIBS) $(GTK_LIBS) $(LIBM)
-endif