openal: Add new openalsrc element
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Mon, 23 May 2011 12:14:09 +0000 (14:14 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Mon, 23 May 2011 12:30:11 +0000 (14:30 +0200)
Based on patches by Victor Lin <bornstub@gmail.com>

Fixes bug #550230.

ext/openal/Makefile.am
ext/openal/gstopenal.c
ext/openal/gstopenalsrc.c [new file with mode: 0644]
ext/openal/gstopenalsrc.h [new file with mode: 0644]

index a80e34fff777bf9de20b0d483d5ad60486506fac..2110689da9b5a89c6b13ff98e5727649d373d2a6 100644 (file)
@@ -3,7 +3,7 @@
 plugin_LTLIBRARIES = libgstopenal.la
 
 # sources used to compile this plug-in
-libgstopenal_la_SOURCES = gstopenal.c gstopenalsink.c
+libgstopenal_la_SOURCES = gstopenal.c gstopenalsink.c gstopenalsrc.c
 
 # compiler and linker flags used to compile this plugin, set in configure.ac
 libgstopenal_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(OPENAL_CFLAGS)
@@ -12,4 +12,4 @@ libgstopenal_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstopenal_la_LIBTOOLFLAGS = --tag=disable-static
 
 # headers we need but don't want installed
-noinst_HEADERS = gstopenalsink.h
+noinst_HEADERS = gstopenalsink.h gstopenalsrc.c
index c8bee0554b21f2c926771007e0f14a123ade3f5c..7022441b533434d383766090d6a6547d3ae60721 100644 (file)
 #include <gst/gst-i18n-plugin.h>
 
 #include "gstopenalsink.h"
+#include "gstopenalsrc.h"
 
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
   if (!gst_element_register (plugin, "openalsink", GST_RANK_SECONDARY,
-          GST_TYPE_OPENAL_SINK))
+          GST_TYPE_OPENAL_SINK) ||
+      !gst_element_register (plugin, "openalsrc", GST_RANK_SECONDARY,
+          GST_TYPE_OPENAL_SRC))
     return FALSE;
 
 #ifdef ENABLE_NLS
diff --git a/ext/openal/gstopenalsrc.c b/ext/openal/gstopenalsrc.c
new file mode 100644 (file)
index 0000000..3500719
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * GStreamer
+ * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
+ * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2008 Victor Lin <bornstub@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * 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.
+ */
+
+ /**
+ * SECTION:element-openalsrc
+ * @short_description: record sound from your sound card using OpenAL
+ *
+ * <refsect2>
+ * <para>
+ * This element lets you record sound using the OpenAL
+ * </para>
+ * <title>Example pipelines</title>
+ * <para>
+ * <programlisting>
+ * gst-launch -v openalsrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=mymusic.ogg
+ * </programlisting>
+ * will record sound from your sound card using OpenAL and encode it to an Ogg/Vorbis file
+ * </para>
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <gst/gst.h>
+#include <gst/gsterror.h>
+
+#include "gstopenalsrc.h"
+
+GST_DEBUG_CATEGORY_STATIC (openalsrc_debug);
+
+#define GST_CAT_DEFAULT openalsrc_debug
+
+#define DEFAULT_DEVICE              NULL
+#define DEFAULT_DEVICE_NAME         NULL
+
+/**
+    Filter signals and args
+**/
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+
+/**
+    Properties
+**/
+enum
+{
+  PROP_0,
+  PROP_DEVICE,
+  PROP_DEVICE_NAME
+};
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-int, "
+        "endianness = (int) BYTE_ORDER, "
+        "signed = (boolean) TRUE, "
+        "width = (int) 16, "
+        "depth = (int) 16, "
+        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
+        "audio/x-raw-int, "
+        "signed = (boolean) TRUE, "
+        "width = (int) 8, "
+        "depth = (int) 8, "
+        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
+    );
+
+GST_BOILERPLATE (GstOpenalSrc, gst_openal_src, GstAudioSrc, GST_TYPE_AUDIO_SRC);
+
+static void gst_openal_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_openal_src_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static gboolean gst_openal_src_open (GstAudioSrc * src);
+static gboolean
+gst_openal_src_prepare (GstAudioSrc * src, GstRingBufferSpec * spec);
+static gboolean gst_openal_src_unprepare (GstAudioSrc * src);
+static gboolean gst_openal_src_close (GstAudioSrc * src);
+static guint
+gst_openal_src_read (GstAudioSrc * src, gpointer data, guint length);
+static guint gst_openal_src_delay (GstAudioSrc * src);
+static void gst_openal_src_reset (GstAudioSrc * src);
+
+static void gst_openal_src_finalize (GObject * object);
+
+static void
+gst_openal_src_base_init (gpointer gclass)
+{
+
+  GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
+
+  gst_element_class_set_details_simple (element_class, "OpenAL src",
+      "Source/Audio",
+      "OpenAL source capture audio from device",
+      "Victor Lin <bornstub@gmail.com>");
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&src_factory)
+      );
+}
+
+static void
+gst_openal_src_class_init (GstOpenalSrcClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstAudioSrcClass *gstaudio_src_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gstaudio_src_class = GST_AUDIO_SRC_CLASS (klass);
+
+  GST_DEBUG_CATEGORY_INIT (openalsrc_debug, "openalsrc",
+      0, "OpenAL source capture audio from device");
+
+  gobject_class->set_property = gst_openal_src_set_property;
+  gobject_class->get_property = gst_openal_src_get_property;
+  gobject_class->finalize = gst_openal_src_finalize;
+
+  gstaudio_src_class->open = GST_DEBUG_FUNCPTR (gst_openal_src_open);
+  gstaudio_src_class->prepare = GST_DEBUG_FUNCPTR (gst_openal_src_prepare);
+  gstaudio_src_class->unprepare = GST_DEBUG_FUNCPTR (gst_openal_src_unprepare);
+  gstaudio_src_class->close = GST_DEBUG_FUNCPTR (gst_openal_src_close);
+  gstaudio_src_class->read = GST_DEBUG_FUNCPTR (gst_openal_src_read);
+  gstaudio_src_class->delay = GST_DEBUG_FUNCPTR (gst_openal_src_delay);
+  gstaudio_src_class->reset = GST_DEBUG_FUNCPTR (gst_openal_src_reset);
+
+  g_object_class_install_property (gobject_class,
+      PROP_DEVICE,
+      g_param_spec_string ("device",
+          "Device",
+          "Specific capture device to open, NULL indicate default device",
+          DEFAULT_DEVICE, G_PARAM_READWRITE)
+      );
+
+  g_object_class_install_property (gobject_class,
+      PROP_DEVICE_NAME,
+      g_param_spec_string ("device-name",
+          "Device name",
+          "Readable name of device", DEFAULT_DEVICE_NAME, G_PARAM_READABLE)
+      );
+}
+
+static void
+gst_openal_src_init (GstOpenalSrc * osrc, GstOpenalSrcClass * gclass)
+{
+  osrc->deviceName = g_strdup (DEFAULT_DEVICE_NAME);
+  osrc->device = DEFAULT_DEVICE;
+  osrc->deviceHandle = NULL;
+}
+
+static void
+gst_openal_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstOpenalSrc *osrc = GST_OPENAL_SRC (object);
+
+  switch (prop_id) {
+    case PROP_DEVICE:
+      osrc->device = g_value_dup_string (value);
+      break;
+    case PROP_DEVICE_NAME:
+      osrc->deviceName = g_value_dup_string (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_openal_src_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstOpenalSrc *osrc = GST_OPENAL_SRC (object);
+
+  switch (prop_id) {
+    case PROP_DEVICE:
+      g_value_set_string (value, osrc->device);
+      break;
+    case PROP_DEVICE_NAME:
+      g_value_set_string (value, osrc->deviceName);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static gboolean
+gst_openal_src_open (GstAudioSrc * asrc)
+{
+  /* We don't do anything here */
+  return TRUE;
+}
+
+static gboolean
+gst_openal_src_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
+{
+
+  GstOpenalSrc *osrc = GST_OPENAL_SRC (asrc);
+  ALenum format;
+  guint64 bufferSize;
+
+  switch (spec->width) {
+    case 8:
+      format = AL_FORMAT_STEREO8;
+      break;
+    case 16:
+      format = AL_FORMAT_STEREO16;
+      break;
+    default:
+      g_assert_not_reached ();
+  }
+
+  bufferSize =
+      spec->buffer_time * spec->rate * spec->bytes_per_sample / 1000000;
+
+  GST_INFO_OBJECT (osrc, "Open device : %s", osrc->deviceName);
+  osrc->deviceHandle =
+      alcCaptureOpenDevice (osrc->device, spec->rate, format, bufferSize);
+
+  if (!osrc->deviceHandle) {
+    GST_ELEMENT_ERROR (osrc,
+        RESOURCE,
+        FAILED,
+        ("Can't open device \"%s\"", osrc->device),
+        ("Can't open device \"%s\"", osrc->device)
+        );
+    return FALSE;
+  }
+
+  osrc->deviceName =
+      g_strdup (alcGetString (osrc->deviceHandle, ALC_DEVICE_SPECIFIER));
+  osrc->bytes_per_sample = spec->bytes_per_sample;
+
+  GST_INFO_OBJECT (osrc, "Start capture");
+  alcCaptureStart (osrc->deviceHandle);
+
+  return TRUE;
+}
+
+static gboolean
+gst_openal_src_unprepare (GstAudioSrc * asrc)
+{
+
+  GstOpenalSrc *osrc = GST_OPENAL_SRC (asrc);
+
+  GST_INFO_OBJECT (osrc, "Close device : %s", osrc->deviceName);
+  if (osrc->deviceHandle) {
+    alcCaptureStop (osrc->deviceHandle);
+    alcCaptureCloseDevice (osrc->deviceHandle);
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_openal_src_close (GstAudioSrc * asrc)
+{
+  /* We don't do anything here */
+  return TRUE;
+}
+
+static guint
+gst_openal_src_read (GstAudioSrc * asrc, gpointer data, guint length)
+{
+  GstOpenalSrc *osrc = GST_OPENAL_SRC (asrc);
+  gint samples;
+
+  alcGetIntegerv (osrc->deviceHandle, ALC_CAPTURE_SAMPLES, sizeof (samples),
+      &samples);
+
+  if (samples * osrc->bytes_per_sample > length) {
+    samples = length / osrc->bytes_per_sample;
+  }
+
+  if (samples) {
+    GST_DEBUG_OBJECT (osrc, "Read samples : %d", samples);
+    alcCaptureSamples (osrc->deviceHandle, data, samples);
+  }
+
+  return samples * osrc->bytes_per_sample;
+}
+
+static guint
+gst_openal_src_delay (GstAudioSrc * asrc)
+{
+  GstOpenalSrc *osrc = GST_OPENAL_SRC (asrc);
+  gint samples;
+
+  alcGetIntegerv (osrc->deviceHandle, ALC_CAPTURE_SAMPLES, sizeof (samples),
+      &samples);
+
+  return samples;
+}
+
+static void
+gst_openal_src_reset (GstAudioSrc * asrc)
+{
+  /* We don't do anything here */
+}
+
+static void
+gst_openal_src_finalize (GObject * object)
+{
+  GstOpenalSrc *osrc = GST_OPENAL_SRC (object);
+
+  g_free (osrc->deviceName);
+  g_free (osrc->device);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
diff --git a/ext/openal/gstopenalsrc.h b/ext/openal/gstopenalsrc.h
new file mode 100644 (file)
index 0000000..d8cde4d
--- /dev/null
@@ -0,0 +1,105 @@
+/*\r
+ * GStreamer\r
+ * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>\r
+ * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>\r
+ * Copyright (C) 2008 Victor Lin <bornstub@gmail.com>\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a\r
+ * copy of this software and associated documentation files (the "Software"),\r
+ * to deal in the Software without restriction, including without limitation\r
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
+ * and/or sell copies of the Software, and to permit persons to whom the\r
+ * Software is furnished to do so, subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in\r
+ * all copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
+ * DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * Alternatively, the contents of this file may be used under the\r
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in\r
+ * which case the following provisions apply instead of the ones\r
+ * mentioned above:\r
+ *\r
+ * This library is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU Library General Public\r
+ * License as published by the Free Software Foundation; either\r
+ * version 2 of the License, or (at your option) any later version.\r
+ *\r
+ * This library is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+ * Library General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU Library General Public\r
+ * License along with this library; if not, write to the\r
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
+ * Boston, MA 02111-1307, USA.\r
+ */\r
+\r
+#ifndef __GST_OPENAL_SRC_H__\r
+#define __GST_OPENAL_SRC_H__\r
+\r
+#include <gst/gst.h>\r
+#include <gst/audio/gstaudiosrc.h>\r
+\r
+#ifdef _WIN32\r
+#include <al.h>\r
+#include <alc.h>\r
+#include <alext.h>\r
+#elif defined(__APPLE__)\r
+#include <OpenAL/al.h>\r
+#include <OpenAL/alc.h>\r
+#include <OpenAL/alext.h>\r
+#else\r
+#include <AL/al.h>\r
+#include <AL/alc.h>\r
+#include <AL/alext.h>\r
+#endif\r
+\r
+G_BEGIN_DECLS\r
+\r
+#define GST_TYPE_OPENAL_SRC \\r
+  (gst_openal_src_get_type())\r
+#define GST_OPENAL_SRC(obj) \\r
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OPENAL_SRC,GstOpenalSrc))\r
+#define GST_OPENAL_SRC_CLASS(klass) \\r
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OPENAL_SRC,GstOpenalSrcClass))\r
+#define GST_IS_OPENAL_SRC(obj) \\r
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OPENAL_SRC))\r
+#define GST_IS_OPENAL_SRC_CLASS(klass) \\r
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OPENAL_SRC))\r
+\r
+typedef struct _GstOpenalSrc      GstOpenalSrc;\r
+typedef struct _GstOpenalSrcClass GstOpenalSrcClass;\r
+\r
+struct _GstOpenalSrc {\r
+       GstAudioSrc element;\r
+       GstPad *srcpad;\r
+       gboolean silent;\r
+\r
+       /* readable name of device */\r
+       gchar *deviceName;\r
+       /* name of device to open, default is a NULL pointer to get default device */\r
+       gchar *device;\r
+       /* OpenAL device handle */\r
+       ALCdevice *deviceHandle;\r
+\r
+        guint bytes_per_sample;\r
+};\r
+\r
+struct _GstOpenalSrcClass {\r
+       GstAudioSrcClass parent_class;\r
+};\r
+\r
+GType gst_openal_src_get_type (void);\r
+\r
+G_END_DECLS\r
+\r
+#endif /* __GST_OPENAL_SRC_H__ */\r