gst/volume/Makefile.am: gst/volume/demo.c gst/volume/gstvolume.h
authorAndy Wingo <wingo@pobox.com>
Mon, 9 May 2005 21:37:17 +0000 (21:37 +0000)
committerAndy Wingo <wingo@pobox.com>
Mon, 9 May 2005 21:37:17 +0000 (21:37 +0000)
Original commit message from CVS:
2005-05-09  Andy Wingo  <wingo@pobox.com>

* gst/volume/Makefile.am:
* gst/volume/demo.c
* gst/volume/gstvolume.h
* gst/volume/gstvolume.c: Port to 0.9 API, derive from
basetransform. Probably need an audio filter base class.

ChangeLog
configure.ac
gst/volume/Makefile.am
gst/volume/demo.c
gst/volume/gstvolume.c
gst/volume/gstvolume.h

index 1b6bce9590dc4981fb5f29a87dcd0d1096866545..a799909071c850218ccec614c173124eab359a57 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2005-05-09  Andy Wingo  <wingo@pobox.com>
+
+       * gst/volume/Makefile.am:
+       * gst/volume/demo.c
+       * gst/volume/gstvolume.h
+       * gst/volume/gstvolume.c: Port to 0.9 API, derive from
+       basetransform. Probably need an audio filter base class.
+
 2005-05-09  Wim Taymans  <wim@fluendo.com>
 
        * ext/vorbis/vorbisenc.c: (gst_vorbisenc_sink_setcaps),
index f500013886bc02d4234a56418bce9902ca81757b..8519e9dfb43b9eda259d6050ecd5d47aac646889 100644 (file)
@@ -377,6 +377,7 @@ GST_PLUGINS_ALL="\
         subparse \
        typefind \
        videotestsrc \
+        volume \
        "
 
 dnl see if we can build C++ plug-ins
@@ -873,6 +874,7 @@ gst/sine/Makefile
 gst/subparse/Makefile
 gst/typefind/Makefile
 gst/videotestsrc/Makefile
+gst/volume/Makefile
 sys/Makefile
 sys/ximage/Makefile
 sys/xvimage/Makefile
index 2ad38c59b0dc003922f8b3210ee7a2d3d2b242a4..2440ccf5676ebe75508486bbc0a535704c5cc706 100644 (file)
@@ -4,7 +4,8 @@ plugin_LTLIBRARIES = libgstvolume.la
 libgstvolume_la_SOURCES = gstvolume.c
 libgstvolume_la_CFLAGS = $(GST_CFLAGS)
 libgstvolume_la_LIBADD = $(GST_LIBS) $(GST_CONTROL_LIBS) \
-       $(top_builddir)/gst-libs/gst/libgstinterfaces-$(GST_MAJORMINOR).la
+       $(top_builddir)/gst-libs/gst/libgstinterfaces-$(GST_MAJORMINOR).la \
+       $(GST_BASE_LIBS)
 libgstvolume_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
 noinst_HEADERS = gstvolume.h filter.func
index 1dfc6ba54e1542441a4e569ad9231914dda34d68..ebcbadae57d171777bdeac17f0f55d99b3a0330f 100644 (file)
@@ -49,18 +49,6 @@ value_changed_callback (GtkWidget * widget, GstElement * volume)
   g_object_set (volume, "volume", level, NULL);
 }
 
-static gboolean
-idler (gpointer data)
-{
-  GstElement *pipeline = GST_ELEMENT (data);
-
-  g_print ("+");
-  if (gst_bin_iterate (GST_BIN (pipeline)))
-    return TRUE;
-  gtk_main_quit ();
-  return FALSE;
-}
-
 static void
 setup_gui (GstElement * volume)
 {
@@ -128,9 +116,9 @@ main (int argc, char *argv[])
 
   /* go to main loop */
   gst_element_set_state (pipeline, GST_STATE_PLAYING);
-  g_idle_add (idler, pipeline);
-
-  gtk_main ();
+  gst_bus_poll (gst_element_get_bus (pipeline),
+      GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
+  gst_element_set_state (pipeline, GST_STATE_NULL);
 
   return 0;
 }
index 89dd25c4c7eb0cdf48184a8afab25bce1a64ed22..42242d75057bc102de14072c79ae43db03659b67 100644 (file)
@@ -23,6 +23,7 @@
 #endif
 #include <string.h>
 #include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
 #include <gst/audio/audio.h>
 #include <gst/control/control.h>
 #include <gst/mixer/mixer.h>
@@ -46,7 +47,7 @@ static GstElementDetails volume_details = {
   "Volume",
   "Filter/Effect/Audio",
   "Set volume on audio/raw streams",
-  "Andy Wingo <apwingo@eos.ncsu.edu>",
+  "Andy Wingo <wingo@pobox.com>",
 };
 
 
@@ -59,10 +60,10 @@ enum
 
 enum
 {
-  ARG_0,
-  ARG_SILENT,
-  ARG_MUTE,
-  ARG_VOLUME
+  PROP_0,
+  PROP_SILENT,
+  PROP_MUTE,
+  PROP_VOLUME
 };
 
 static GstStaticPadTemplate volume_sink_factory =
@@ -98,9 +99,30 @@ static GstStaticPadTemplate volume_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
         "width = (int) 16, " "depth = (int) 16, " "signed = (bool) TRUE")
     );
 
-static void volume_base_init (gpointer g_class);
-static void volume_class_init (GstVolumeClass * klass);
-static void volume_init (GstVolume * filter);
+static void gst_volume_interface_init (GstImplementsInterfaceClass * klass);
+static void gst_volume_mixer_init (GstMixerClass * iface);
+
+#define _init_interfaces(type)                                                         \
+  {                                                                             \
+    static const GInterfaceInfo voliface_info = {                               \
+      (GInterfaceInitFunc) gst_volume_interface_init,                           \
+      NULL,                                                                     \
+      NULL                                                                      \
+    };                                                                          \
+    static const GInterfaceInfo volmixer_info = {                               \
+      (GInterfaceInitFunc) gst_volume_mixer_init,                               \
+      NULL,                                                                     \
+      NULL                                                                      \
+    };                                                                          \
+                                                                                \
+    g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,           \
+        &voliface_info);                                                        \
+    g_type_add_interface_static (type, GST_TYPE_MIXER, &volmixer_info);         \
+  }
+
+GST_BOILERPLATE_FULL (GstVolume, gst_volume, GstBaseTransform,
+    GST_TYPE_BASE_TRANSFORM, _init_interfaces);
+
 
 static void volume_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
@@ -109,18 +131,12 @@ static void volume_get_property (GObject * object, guint prop_id,
 static void volume_update_volume (const GValue * value, gpointer data);
 static void volume_update_mute (const GValue * value, gpointer data);
 
-static gboolean volume_parse_caps (GstVolume * filter,
-    GstStructure * structure);
-
-static void volume_chain_float (GstPad * pad, GstData * _data);
-static void volume_chain_int16 (GstPad * pad, GstData * _data);
-
-static void gst_volume_interface_init (GstImplementsInterfaceClass * klass);
-static void gst_volume_mixer_init (GstMixerClass * iface);
-
-static GstElementClass *parent_class = NULL;
-
-/*static guint gst_filter_signals[LAST_SIGNAL] = { 0 }; */
+static GstFlowReturn volume_transform (GstBaseTransform * base,
+    GstBuffer * inbuf, GstBuffer ** outbuf);
+static void volume_process_float (GstVolume * filter, GstClockTime tstamp,
+    gpointer bytes, gint n_bytes);
+static void volume_process_int16 (GstVolume * filter, GstClockTime tstamp,
+    gpointer bytes, gint n_bytes);
 
 static gboolean
 gst_volume_interface_supported (GstImplementsInterface * iface, GType type)
@@ -233,97 +249,8 @@ gst_volume_dispose (GObject * object)
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
-static GstPadLinkReturn
-volume_connect (GstPad * pad, const GstCaps * caps)
-{
-  GstVolume *filter;
-  GstPad *otherpad;
-  gint rate;
-  GstPadLinkReturn link_ret;
-  GstStructure *structure;
-
-  filter = GST_VOLUME (gst_pad_get_parent (pad));
-  g_return_val_if_fail (GST_IS_VOLUME (filter), GST_PAD_LINK_REFUSED);
-  otherpad = (pad == filter->srcpad ? filter->sinkpad : filter->srcpad);
-
-  structure = gst_caps_get_structure (caps, 0);
-  gst_structure_get_int (structure, "rate", &rate);
-
-  link_ret = gst_pad_try_set_caps (otherpad, caps);
-  if (GST_PAD_LINK_FAILED (link_ret)) {
-    return link_ret;
-  }
-
-  if (!volume_parse_caps (filter, structure))
-    return GST_PAD_LINK_REFUSED;
-
-  gst_dpman_set_rate (filter->dpman, rate);
-
-  return GST_PAD_LINK_OK;
-}
-
-static gboolean
-volume_parse_caps (GstVolume * filter, GstStructure * structure)
-{
-  const gchar *mimetype;
-
-  g_return_val_if_fail (filter != NULL, FALSE);
-  g_return_val_if_fail (structure != NULL, FALSE);
-
-  mimetype = gst_structure_get_name (structure);
-
-  if (strcmp (mimetype, "audio/x-raw-int") == 0) {
-    gst_pad_set_chain_function (filter->sinkpad, volume_chain_int16);
-    return TRUE;
-  }
-
-  if (strcmp (mimetype, "audio/x-raw-float") == 0) {
-    gst_pad_set_chain_function (filter->sinkpad, volume_chain_float);
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-
-GType
-gst_volume_get_type (void)
-{
-  static GType volume_type = 0;
-
-  if (!volume_type) {
-    static const GTypeInfo volume_info = {
-      sizeof (GstVolumeClass),
-      volume_base_init,
-      NULL,
-      (GClassInitFunc) volume_class_init,
-      NULL,
-      NULL,
-      sizeof (GstVolume),
-      0,
-      (GInstanceInitFunc) volume_init
-    };
-    static const GInterfaceInfo voliface_info = {
-      (GInterfaceInitFunc) gst_volume_interface_init,
-      NULL,
-      NULL
-    };
-    static const GInterfaceInfo volmixer_info = {
-      (GInterfaceInitFunc) gst_volume_mixer_init,
-      NULL,
-      NULL
-    };
-
-    volume_type =
-        g_type_register_static (GST_TYPE_ELEMENT, "GstVolume", &volume_info, 0);
-    g_type_add_interface_static (volume_type, GST_TYPE_IMPLEMENTS_INTERFACE,
-        &voliface_info);
-    g_type_add_interface_static (volume_type, GST_TYPE_MIXER, &volmixer_info);
-  }
-  return volume_type;
-}
 static void
-volume_base_init (gpointer g_class)
+gst_volume_base_init (gpointer g_class)
 {
   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 
@@ -333,51 +260,32 @@ volume_base_init (gpointer g_class)
       gst_static_pad_template_get (&volume_sink_factory));
   gst_element_class_set_details (element_class, &volume_details);
 }
+
 static void
-volume_class_init (GstVolumeClass * klass)
+gst_volume_class_init (GstVolumeClass * klass)
 {
   GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
 
   gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-
-  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+  gobject_class->set_property = volume_set_property;
+  gobject_class->get_property = volume_get_property;
+  gobject_class->dispose = gst_volume_dispose;
 
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MUTE,
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MUTE,
       g_param_spec_boolean ("mute", "mute", "mute", FALSE, G_PARAM_READWRITE));
 
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VOLUME,
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VOLUME,
       g_param_spec_double ("volume", "volume", "volume",
           0.0, VOLUME_MAX_DOUBLE, 1.0, G_PARAM_READWRITE));
 
-  gobject_class->set_property = volume_set_property;
-  gobject_class->get_property = volume_get_property;
-  gobject_class->dispose = gst_volume_dispose;
+  GST_BASE_TRANSFORM_CLASS (klass)->transform = volume_transform;
 }
 
 static void
-volume_init (GstVolume * filter)
+gst_volume_init (GstVolume * filter)
 {
   GstMixerTrack *track = NULL;
 
-  filter->sinkpad =
-      gst_pad_new_from_template (gst_static_pad_template_get
-      (&volume_sink_factory), "sink");
-  gst_pad_set_getcaps_function (filter->sinkpad, gst_pad_proxy_getcaps);
-  gst_pad_set_link_function (filter->sinkpad, volume_connect);
-
-  filter->srcpad =
-      gst_pad_new_from_template (gst_static_pad_template_get
-      (&volume_src_factory), "src");
-  gst_pad_set_getcaps_function (filter->srcpad, gst_pad_proxy_getcaps);
-  gst_pad_set_link_function (filter->srcpad, volume_connect);
-
-  gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
-  gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
-
-  gst_pad_set_chain_function (filter->sinkpad, volume_chain_int16);
-
   filter->mute = FALSE;
   filter->volume_i = VOLUME_UNITY_INT;
   filter->volume_f = 1.0;
@@ -407,65 +315,77 @@ volume_init (GstVolume * filter)
 }
 
 static void
-volume_chain_float (GstPad * pad, GstData * _data)
+volume_typefind (GstVolume * filter, const GstStructure * structure)
 {
-  GstBuffer *buf = GST_BUFFER (_data);
-  GstVolume *filter;
-  GstBuffer *out_buf;
-  gfloat *data;
-  gint i, num_samples;
+  const gchar *mimetype;
 
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (buf != NULL);
+  mimetype = gst_structure_get_name (structure);
 
-  filter = GST_VOLUME (GST_OBJECT_PARENT (pad));
-  g_return_if_fail (GST_IS_VOLUME (filter));
+  if (strcmp (mimetype, "audio/x-raw-int") == 0)
+    filter->process = volume_process_int16;
+  else if (strcmp (mimetype, "audio/x-raw-float") == 0)
+    filter->process = volume_process_float;
+}
 
-  GST_LOG_OBJECT (filter, "processing incoming float buffer with refcount %d",
-      GST_BUFFER_REFCOUNT_VALUE (buf));
-  out_buf = gst_buffer_copy_on_write (buf);
+static GstFlowReturn
+volume_transform (GstBaseTransform * base, GstBuffer * inbuf,
+    GstBuffer ** outbuf)
+{
+  GstVolume *filter = GST_VOLUME (base);
 
-  data = (gfloat *) GST_BUFFER_DATA (out_buf);
-  num_samples = GST_BUFFER_SIZE (out_buf) / sizeof (gfloat);
-  GST_DPMAN_PREPROCESS (filter->dpman, num_samples,
-      GST_BUFFER_TIMESTAMP (out_buf));
-  i = 0;
+  if (G_UNLIKELY (!filter->process)) {
+    GstCaps *caps = GST_BUFFER_CAPS (inbuf);
 
-  while (GST_DPMAN_PROCESS (filter->dpman, i)) {
-    data[i++] *= filter->real_vol_f;
+    if (gst_caps_get_size (caps) == 1)
+      volume_typefind (filter, gst_caps_get_structure (caps, 0));
+
+    if (!filter->process) {
+      GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION,
+          ("Invalid caps on first buffer"), NULL);
+      return GST_FLOW_UNEXPECTED;
+    }
   }
 
-  gst_pad_push (filter->srcpad, GST_DATA (out_buf));
+  *outbuf = gst_buffer_copy_on_write (gst_buffer_ref (inbuf));
+
+  filter->process (filter, GST_BUFFER_TIMESTAMP (*outbuf),
+      GST_BUFFER_DATA (*outbuf), GST_BUFFER_SIZE (*outbuf));
 
+  return GST_FLOW_OK;
 }
 
 static void
-volume_chain_int16 (GstPad * pad, GstData * _data)
+volume_process_float (GstVolume * filter, GstClockTime tstamp,
+    gpointer bytes, gint n_bytes)
 {
-  GstBuffer *buf = GST_BUFFER (_data);
-  GstVolume *filter;
-  GstBuffer *out_buf;
-  gint16 *data;
+  gfloat *data;
   gint i, num_samples;
 
-  g_return_if_fail (_data);
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (buf != NULL);
+  data = (gfloat *) bytes;
+  num_samples = n_bytes / sizeof (gfloat);
 
-  filter = GST_VOLUME (GST_OBJECT_PARENT (pad));
-  g_return_if_fail (GST_IS_VOLUME (filter));
+  GST_DPMAN_PREPROCESS (filter->dpman, num_samples, tstamp);
 
-  GST_LOG_OBJECT (filter, "processing incoming int16 buffer with refcount %d",
-      GST_BUFFER_REFCOUNT_VALUE (buf));
-  out_buf = gst_buffer_copy_on_write (buf);
+  i = 0;
+  while (GST_DPMAN_PROCESS (filter->dpman, i)) {
+    data[i++] *= filter->real_vol_f;
+  }
+}
 
-  data = (gint16 *) GST_BUFFER_DATA (out_buf);
-  g_assert (data);
-  num_samples = GST_BUFFER_SIZE (out_buf) / sizeof (gint16);
-  GST_DPMAN_PREPROCESS (filter->dpman, num_samples,
-      GST_BUFFER_TIMESTAMP (out_buf));
+static void
+volume_process_int16 (GstVolume * filter, GstClockTime tstamp,
+    gpointer bytes, gint n_bytes)
+{
+  gint16 *data;
+  gint i, num_samples;
+
+  data = (gint16 *) bytes;
+  num_samples = n_bytes / sizeof (gint16);
+
+  GST_DPMAN_PREPROCESS (filter->dpman, num_samples, tstamp);
   i = 0;
 
+  /* need... liboil... */
   while (GST_DPMAN_PROCESS (filter->dpman, i)) {
     /* only clamp if the gain is greater than 1.0 */
     if (filter->real_vol_i > VOLUME_UNITY_INT) {
@@ -487,8 +407,6 @@ volume_chain_int16 (GstPad * pad, GstData * _data)
       }
     }
   }
-
-  gst_pad_push (filter->srcpad, GST_DATA (out_buf));
 }
 
 static void
@@ -535,18 +453,14 @@ static void
 volume_set_property (GObject * object, guint prop_id, const GValue * value,
     GParamSpec * pspec)
 {
-  GstVolume *filter;
-
-  /* it's not null if we got it, but it might not be ours */
-  g_return_if_fail (GST_IS_VOLUME (object));
-  filter = GST_VOLUME (object);
+  GstVolume *filter = GST_VOLUME (object);
 
   switch (prop_id) {
-    case ARG_MUTE:
+    case PROP_MUTE:
       gst_dpman_bypass_dparam (filter->dpman, "mute");
       volume_update_mute (value, filter);
       break;
-    case ARG_VOLUME:
+    case PROP_VOLUME:
       gst_dpman_bypass_dparam (filter->dpman, "volume");
       volume_update_volume (value, filter);
       break;
@@ -560,17 +474,13 @@ static void
 volume_get_property (GObject * object, guint prop_id, GValue * value,
     GParamSpec * pspec)
 {
-  GstVolume *filter;
-
-  /* it's not null if we got it, but it might not be ours */
-  g_return_if_fail (GST_IS_VOLUME (object));
-  filter = GST_VOLUME (object);
+  GstVolume *filter = GST_VOLUME (object);
 
   switch (prop_id) {
-    case ARG_MUTE:
+    case PROP_MUTE:
       g_value_set_boolean (value, filter->mute);
       break;
-    case ARG_VOLUME:
+    case PROP_VOLUME:
       g_value_set_double (value, filter->volume_f);
       break;
     default:
index 5a481c8a2706defda76fc985019981b8e341b24c..e48a2d714d4c2cb0b37c97bce12b9491fcc8246d 100644 (file)
 
 
 #include <gst/gst.h>
-/* #include <gst/meta/audioraw.h> */
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+G_BEGIN_DECLS
 
 
 #define GST_TYPE_VOLUME \
@@ -37,7 +34,7 @@ extern "C" {
 #define GST_VOLUME(obj) \
   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VOLUME,GstVolume))
 #define GST_VOLUME_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ULAW,GstVolume))
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VOLUME,GstVolume))
 #define GST_IS_VOLUME(obj) \
   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VOLUME))
 #define GST_IS_VOLUME_CLASS(obj) \
@@ -53,9 +50,10 @@ enum _GstVolumeFormat {
 };
 
 struct _GstVolume {
-  GstElement element;
+  GstBaseTransform element;
+
+  void (*process)(GstVolume*, GstClockTime, gpointer, gint);
 
-  GstPad *sinkpad, *srcpad;
   GstDParamManager *dpman;
 
   gboolean mute;
@@ -66,14 +64,13 @@ struct _GstVolume {
 };
 
 struct _GstVolumeClass {
-  GstElementClass parent_class;
+  GstBaseTransformClass parent_class;
 };
 
 GType gst_volume_get_type(void);
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+
+G_END_DECLS
 
 
 #endif /* __GST_VOLUME_H__ */