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))
-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
$(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 = \
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);
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,
} else {
GST_INFO_OBJECT (ogg, "Seek failed, duration will stay unknown");
ogg->push_state = PUSH_PLAYING;
+ ogg->push_disable_seeking = TRUE;
return FALSE;
}
}
break;
}
- /* consumer header packet/frame */
- gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (vd), NULL, 1);
-
return res;
/* ERRORS */
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)
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;
{
GstFlowReturn ret;
- if (dec->priv->drained)
+ if (dec->priv->drained && !dec->priv->gather)
return GST_FLOW_OK;
else {
/* dispatch reverse pending buffers */
"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,
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 \
+++ /dev/null
-/* 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;
-}
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
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, \
{
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);
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! */
}
}
+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:
*
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));
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;
}
}
}
+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)
{
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);
ret = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
}
- gst_object_unref (otherpad);
gst_object_unref (self);
return ret;
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);
}
}
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);
}
}
/* Unblock pads */
unblock_video (self);
unblock_subtitle (self);
-
goto out;
} else if (target) {
gst_object_unref (target);
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)));
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,
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,
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);
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",
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",
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
+
+audiomix
testchannels
+volume
+
+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
--- /dev/null
+/* 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;
+}
#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))
+++ /dev/null
-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