summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/Makefile.am84
-rw-r--r--sys/Makefile.in869
-rw-r--r--sys/directsound/Makefile.am18
-rw-r--r--sys/directsound/Makefile.in828
-rw-r--r--sys/directsound/gstdirectsoundplugin.c49
-rw-r--r--sys/directsound/gstdirectsoundsink.c785
-rw-r--r--sys/directsound/gstdirectsoundsink.h97
-rw-r--r--sys/oss/Makefile.am28
-rw-r--r--sys/oss/Makefile.in879
-rw-r--r--sys/oss/common.h43
-rw-r--r--sys/oss/gstossaudio.c61
-rw-r--r--sys/oss/gstossdmabuffer.h77
-rw-r--r--sys/oss/gstosshelper.c407
-rw-r--r--sys/oss/gstosshelper.h43
-rw-r--r--sys/oss/gstossmixer.c378
-rw-r--r--sys/oss/gstossmixer.h171
-rw-r--r--sys/oss/gstossmixerelement.c218
-rw-r--r--sys/oss/gstossmixerelement.h59
-rw-r--r--sys/oss/gstossmixertrack.c172
-rw-r--r--sys/oss/gstossmixertrack.h62
-rw-r--r--sys/oss/gstosssink.c565
-rw-r--r--sys/oss/gstosssink.h62
-rw-r--r--sys/oss/gstosssrc.c537
-rw-r--r--sys/oss/gstosssrc.h67
-rw-r--r--sys/oss4/Makefile.am33
-rw-r--r--sys/oss4/Makefile.in892
-rw-r--r--sys/oss4/oss4-audio.c714
-rw-r--r--sys/oss4/oss4-audio.h43
-rw-r--r--sys/oss4/oss4-mixer-enum.c269
-rw-r--r--sys/oss4/oss4-mixer-enum.h67
-rw-r--r--sys/oss4/oss4-mixer-slider.c311
-rw-r--r--sys/oss4/oss4-mixer-slider.h70
-rw-r--r--sys/oss4/oss4-mixer-switch.c150
-rw-r--r--sys/oss4/oss4-mixer-switch.h65
-rw-r--r--sys/oss4/oss4-mixer.c1862
-rw-r--r--sys/oss4/oss4-mixer.h128
-rw-r--r--sys/oss4/oss4-property-probe.c412
-rw-r--r--sys/oss4/oss4-property-probe.h38
-rw-r--r--sys/oss4/oss4-sink.c696
-rw-r--r--sys/oss4/oss4-sink.h64
-rw-r--r--sys/oss4/oss4-soundcard.h2067
-rw-r--r--sys/oss4/oss4-source.c997
-rw-r--r--sys/oss4/oss4-source.h89
-rw-r--r--sys/osxaudio/Makefile.am26
-rw-r--r--sys/osxaudio/Makefile.in858
-rw-r--r--sys/osxaudio/gstosxaudio.c53
-rw-r--r--sys/osxaudio/gstosxaudioelement.c92
-rw-r--r--sys/osxaudio/gstosxaudioelement.h84
-rw-r--r--sys/osxaudio/gstosxaudiosink.c348
-rw-r--r--sys/osxaudio/gstosxaudiosink.h86
-rw-r--r--sys/osxaudio/gstosxaudiosrc.c362
-rw-r--r--sys/osxaudio/gstosxaudiosrc.h82
-rw-r--r--sys/osxaudio/gstosxringbuffer.c689
-rw-r--r--sys/osxaudio/gstosxringbuffer.h94
-rw-r--r--sys/osxvideo/Makefile.am19
-rw-r--r--sys/osxvideo/Makefile.in824
-rw-r--r--sys/osxvideo/cocoawindow.h74
-rw-r--r--sys/osxvideo/cocoawindow.m432
-rw-r--r--sys/osxvideo/osxvideosink.h85
-rw-r--r--sys/osxvideo/osxvideosink.m524
-rw-r--r--sys/sunaudio/Makefile.am26
-rw-r--r--sys/sunaudio/Makefile.in877
-rw-r--r--sys/sunaudio/gstsunaudio.c63
-rw-r--r--sys/sunaudio/gstsunaudiomixer.c104
-rw-r--r--sys/sunaudio/gstsunaudiomixer.h51
-rw-r--r--sys/sunaudio/gstsunaudiomixerctrl.c585
-rw-r--r--sys/sunaudio/gstsunaudiomixerctrl.h189
-rw-r--r--sys/sunaudio/gstsunaudiomixeroptions.c157
-rw-r--r--sys/sunaudio/gstsunaudiomixeroptions.h65
-rw-r--r--sys/sunaudio/gstsunaudiomixertrack.c158
-rw-r--r--sys/sunaudio/gstsunaudiomixertrack.h78
-rw-r--r--sys/sunaudio/gstsunaudiosink.c651
-rw-r--r--sys/sunaudio/gstsunaudiosink.h78
-rw-r--r--sys/sunaudio/gstsunaudiosrc.c423
-rw-r--r--sys/sunaudio/gstsunaudiosrc.h67
-rw-r--r--sys/v4l2/Makefile.am60
-rw-r--r--sys/v4l2/Makefile.in953
-rw-r--r--sys/v4l2/README32
-rw-r--r--sys/v4l2/gstv4l2.c86
-rw-r--r--sys/v4l2/gstv4l2bufferpool.c652
-rw-r--r--sys/v4l2/gstv4l2bufferpool.h97
-rw-r--r--sys/v4l2/gstv4l2colorbalance.c106
-rw-r--r--sys/v4l2/gstv4l2colorbalance.h104
-rw-r--r--sys/v4l2/gstv4l2object.c2247
-rw-r--r--sys/v4l2/gstv4l2object.h242
-rw-r--r--sys/v4l2/gstv4l2radio.c635
-rw-r--r--sys/v4l2/gstv4l2radio.h67
-rw-r--r--sys/v4l2/gstv4l2sink.c971
-rw-r--r--sys/v4l2/gstv4l2sink.h91
-rw-r--r--sys/v4l2/gstv4l2src.c1072
-rw-r--r--sys/v4l2/gstv4l2src.h102
-rw-r--r--sys/v4l2/gstv4l2tuner.c364
-rw-r--r--sys/v4l2/gstv4l2tuner.h198
-rw-r--r--sys/v4l2/gstv4l2vidorient.c104
-rw-r--r--sys/v4l2/gstv4l2vidorient.h117
-rw-r--r--sys/v4l2/gstv4l2xoverlay.c486
-rw-r--r--sys/v4l2/gstv4l2xoverlay.h70
-rw-r--r--sys/v4l2/v4l2_calls.c925
-rw-r--r--sys/v4l2/v4l2_calls.h142
-rw-r--r--sys/v4l2/v4l2src_calls.c434
-rw-r--r--sys/v4l2/v4l2src_calls.h46
-rw-r--r--sys/waveform/Makefile.am20
-rw-r--r--sys/waveform/Makefile.in828
-rw-r--r--sys/waveform/gstwaveformplugin.c42
-rw-r--r--sys/waveform/gstwaveformsink.c585
-rw-r--r--sys/waveform/gstwaveformsink.h107
-rw-r--r--sys/ximage/Makefile.am16
-rw-r--r--sys/ximage/Makefile.in825
-rw-r--r--sys/ximage/gstximagesrc.c1317
-rw-r--r--sys/ximage/gstximagesrc.h113
-rw-r--r--sys/ximage/ximageutil.c501
-rw-r--r--sys/ximage/ximageutil.h182
112 files changed, 38769 insertions, 0 deletions
diff --git a/sys/Makefile.am b/sys/Makefile.am
new file mode 100644
index 0000000..ab08d04
--- /dev/null
+++ b/sys/Makefile.am
@@ -0,0 +1,84 @@
+# if USE_DXR3
+# DXR3_DIR=dxr3
+# else
+# DXR3_DIR=
+# endif
+
+if USE_OSS
+OSS_DIR=oss
+else
+OSS_DIR=
+endif
+
+if USE_OSS4
+OSS4_DIR=oss4
+else
+OSS4_DIR=
+endif
+
+
+if USE_DIRECTSOUND
+DIRECTSOUND_DIR=directsound
+else
+DIRECTSOUND_DIR=
+endif
+
+if USE_SUNAUDIO
+SUNAUDIO_DIR=sunaudio
+else
+SUNAUDIO_DIR=
+endif
+
+if USE_OSX_AUDIO
+OSX_AUDIO_DIR=osxaudio
+else
+OSX_AUDIO_DIR=
+endif
+
+if USE_OSX_VIDEO
+OSX_VIDEO_DIR=osxvideo
+else
+OSX_VIDEO_DIR=
+endif
+
+# if USE_QCAM
+# QCAM_DIR=qcam
+# else
+# QCAM_DIR=
+# endif
+
+if USE_GST_V4L2
+V4L2_DIR=v4l2
+else
+V4L2_DIR=
+endif
+
+# if USE_VCD
+# VCD_DIR=vcd
+# else
+# VCD_DIR=
+# endif
+
+# if USE_CDROM
+# CDROM_DIR=cdrom
+# else
+# CDROM_DIR=
+# endif
+
+# if USE_OPENGL
+# GL_DIR=glsink
+# else
+# GL_DIR=
+# endif
+
+if USE_X
+XIMAGE_DIR=ximage
+else
+XIMAGE_DIR=
+endif
+
+SUBDIRS=$(DIRECTSOUND_DIR) $(OSS_DIR) $(OSS4_DIR) $(OSX_AUDIO_DIR) $(OSX_VIDEO_DIR) $(SUNAUDIO_DIR) $(V4L2_DIR) $(XIMAGE_DIR)
+
+DIST_SUBDIRS=directsound oss oss4 osxaudio osxvideo sunaudio v4l2 waveform ximage
+
+include $(top_srcdir)/common/parallel-subdirs.mak
diff --git a/sys/Makefile.in b/sys/Makefile.in
new file mode 100644
index 0000000..c37f1df
--- /dev/null
+++ b/sys/Makefile.in
@@ -0,0 +1,869 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# if USE_DXR3
+# DXR3_DIR=dxr3
+# else
+# DXR3_DIR=
+# endif
+
+# include this at the end of $MODULE/ext/Makefile.am to force make to
+# build subdirectories in parallel when make -jN is used. We will end up
+# descending into all subdirectories a second time, but only after the first
+# (parallel) run has finished, so it should go right through the second time.
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/common/parallel-subdirs.mak
+subdir = sys
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
+ $(top_srcdir)/common/m4/as-auto-alt.m4 \
+ $(top_srcdir)/common/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/common/m4/as-gcc-inline-assembly.m4 \
+ $(top_srcdir)/common/m4/as-objc.m4 \
+ $(top_srcdir)/common/m4/as-python.m4 \
+ $(top_srcdir)/common/m4/as-scrub-include.m4 \
+ $(top_srcdir)/common/m4/as-version.m4 \
+ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
+ $(top_srcdir)/common/m4/gst-arch.m4 \
+ $(top_srcdir)/common/m4/gst-args.m4 \
+ $(top_srcdir)/common/m4/gst-check.m4 \
+ $(top_srcdir)/common/m4/gst-default.m4 \
+ $(top_srcdir)/common/m4/gst-dowhile.m4 \
+ $(top_srcdir)/common/m4/gst-error.m4 \
+ $(top_srcdir)/common/m4/gst-feature.m4 \
+ $(top_srcdir)/common/m4/gst-gettext.m4 \
+ $(top_srcdir)/common/m4/gst-glib2.m4 \
+ $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \
+ $(top_srcdir)/common/m4/gst-platform.m4 \
+ $(top_srcdir)/common/m4/gst-plugin-docs.m4 \
+ $(top_srcdir)/common/m4/gst-plugindir.m4 \
+ $(top_srcdir)/common/m4/gst-x11.m4 \
+ $(top_srcdir)/common/m4/gst.m4 \
+ $(top_srcdir)/common/m4/gtk-doc.m4 \
+ $(top_srcdir)/common/m4/orc.m4 $(top_srcdir)/common/m4/pkg.m4 \
+ $(top_srcdir)/m4/aalib.m4 $(top_srcdir)/m4/esd.m4 \
+ $(top_srcdir)/m4/gconf-2.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gst-fionread.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+AALIB_CFLAGS = @AALIB_CFLAGS@
+AALIB_CONFIG = @AALIB_CONFIG@
+AALIB_LIBS = @AALIB_LIBS@
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+ANNODEX_CFLAGS = @ANNODEX_CFLAGS@
+ANNODEX_LIBS = @ANNODEX_LIBS@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BZ2_LIBS = @BZ2_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_GOBJECT_CFLAGS = @CAIRO_GOBJECT_CFLAGS@
+CAIRO_GOBJECT_LIBS = @CAIRO_GOBJECT_LIBS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@
+DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@
+DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@
+DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@
+DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@
+DIRECTSOUND_CFLAGS = @DIRECTSOUND_CFLAGS@
+DIRECTSOUND_LDFLAGS = @DIRECTSOUND_LDFLAGS@
+DIRECTSOUND_LIBS = @DIRECTSOUND_LIBS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DV1394_CFLAGS = @DV1394_CFLAGS@
+DV1394_LIBS = @DV1394_LIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ERROR_CFLAGS = @ERROR_CFLAGS@
+ERROR_CXXFLAGS = @ERROR_CXXFLAGS@
+ESD_CFLAGS = @ESD_CFLAGS@
+ESD_CONFIG = @ESD_CONFIG@
+ESD_LIBS = @ESD_LIBS@
+EXEEXT = @EXEEXT@
+FFLAGS = @FFLAGS@
+FGREP = @FGREP@
+FLAC_CFLAGS = @FLAC_CFLAGS@
+FLAC_LIBS = @FLAC_LIBS@
+GCONFTOOL = @GCONFTOOL@
+GCONF_CFLAGS = @GCONF_CFLAGS@
+GCONF_LIBS = @GCONF_LIBS@
+GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+GCOV = @GCOV@
+GCOV_CFLAGS = @GCOV_CFLAGS@
+GCOV_LIBS = @GCOV_LIBS@
+GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@
+GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_PREFIX = @GLIB_PREFIX@
+GLIB_REQ = @GLIB_REQ@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@
+GSTPB_PREFIX = @GSTPB_PREFIX@
+GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@
+GST_BASE_CFLAGS = @GST_BASE_CFLAGS@
+GST_BASE_LIBS = @GST_BASE_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_CONTROLLER_CFLAGS = @GST_CONTROLLER_CFLAGS@
+GST_CONTROLLER_LIBS = @GST_CONTROLLER_LIBS@
+GST_CXXFLAGS = @GST_CXXFLAGS@
+GST_GDP_CFLAGS = @GST_GDP_CFLAGS@
+GST_GDP_LIBS = @GST_GDP_LIBS@
+GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@
+GST_LIBS = @GST_LIBS@
+GST_LICENSE = @GST_LICENSE@
+GST_LT_LDFLAGS = @GST_LT_LDFLAGS@
+GST_MAJORMINOR = @GST_MAJORMINOR@
+GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@
+GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@
+GST_PACKAGE_NAME = @GST_PACKAGE_NAME@
+GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@
+GST_PLUGINS_ALL = @GST_PLUGINS_ALL@
+GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@
+GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@
+GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@
+GST_PLUGINS_DIR = @GST_PLUGINS_DIR@
+GST_PLUGINS_SELECTED = @GST_PLUGINS_SELECTED@
+GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@
+GST_PREFIX = @GST_PREFIX@
+GST_TOOLS_DIR = @GST_TOOLS_DIR@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_X11_CFLAGS = @GTK_X11_CFLAGS@
+GTK_X11_LIBS = @GTK_X11_LIBS@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+HAVE_AVC1394 = @HAVE_AVC1394@
+HAVE_BZ2 = @HAVE_BZ2@
+HAVE_CXX = @HAVE_CXX@
+HAVE_DIRECTSOUND = @HAVE_DIRECTSOUND@
+HAVE_GCONFTOOL = @HAVE_GCONFTOOL@
+HAVE_ROM1394 = @HAVE_ROM1394@
+HAVE_SPEEX = @HAVE_SPEEX@
+HAVE_X = @HAVE_X@
+HAVE_XSHM = @HAVE_XSHM@
+HAVE_ZLIB = @HAVE_ZLIB@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JACK_0_120_1_CFLAGS = @JACK_0_120_1_CFLAGS@
+JACK_0_120_1_LIBS = @JACK_0_120_1_LIBS@
+JACK_1_9_7_CFLAGS = @JACK_1_9_7_CFLAGS@
+JACK_1_9_7_LIBS = @JACK_1_9_7_LIBS@
+JACK_CFLAGS = @JACK_CFLAGS@
+JACK_LIBS = @JACK_LIBS@
+JPEG_LIBS = @JPEG_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCACA_CFLAGS = @LIBCACA_CFLAGS@
+LIBCACA_LIBS = @LIBCACA_LIBS@
+LIBDV_CFLAGS = @LIBDV_CFLAGS@
+LIBDV_LIBS = @LIBDV_LIBS@
+LIBICONV = @LIBICONV@
+LIBIEC61883_CFLAGS = @LIBIEC61883_CFLAGS@
+LIBIEC61883_LIBS = @LIBIEC61883_LIBS@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBPNG_CFLAGS = @LIBPNG_CFLAGS@
+LIBPNG_LIBS = @LIBPNG_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBV4L2_CFLAGS = @LIBV4L2_CFLAGS@
+LIBV4L2_LIBS = @LIBV4L2_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCALEDIR = @LOCALEDIR@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJC_LDFLAGS = @OBJC_LDFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORCC = @ORCC@
+ORCC_FLAGS = @ORCC_FLAGS@
+ORC_CFLAGS = @ORC_CFLAGS@
+ORC_LIBS = @ORC_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@
+PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PLUGINDIR = @PLUGINDIR@
+POSUB = @POSUB@
+PROFILE_CFLAGS = @PROFILE_CFLAGS@
+PULSE_0_9_20_CFLAGS = @PULSE_0_9_20_CFLAGS@
+PULSE_0_9_20_LIBS = @PULSE_0_9_20_LIBS@
+PULSE_1_0_CFLAGS = @PULSE_1_0_CFLAGS@
+PULSE_1_0_LIBS = @PULSE_1_0_LIBS@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RAW1394_CFLAGS = @RAW1394_CFLAGS@
+RAW1394_LIBS = @RAW1394_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHOUT2_CFLAGS = @SHOUT2_CFLAGS@
+SHOUT2_LIBS = @SHOUT2_LIBS@
+SOUP_CFLAGS = @SOUP_CFLAGS@
+SOUP_LIBS = @SOUP_LIBS@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+TAGLIB_CFLAGS = @TAGLIB_CFLAGS@
+TAGLIB_CXXFLAGS = @TAGLIB_CXXFLAGS@
+TAGLIB_LIBS = @TAGLIB_LIBS@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VALGRIND_PATH = @VALGRIND_PATH@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
+WAVPACK_LIBS = @WAVPACK_LIBS@
+WIN32_LIBS = @WIN32_LIBS@
+XDAMAGE_CFLAGS = @XDAMAGE_CFLAGS@
+XDAMAGE_LIBS = @XDAMAGE_LIBS@
+XFIXES_CFLAGS = @XFIXES_CFLAGS@
+XFIXES_LIBS = @XFIXES_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+XMKMF = @XMKMF@
+XSHM_LIBS = @XSHM_LIBS@
+XVIDEO_LIBS = @XVIDEO_LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+@USE_OSS_FALSE@OSS_DIR =
+@USE_OSS_TRUE@OSS_DIR = oss
+@USE_OSS4_FALSE@OSS4_DIR =
+@USE_OSS4_TRUE@OSS4_DIR = oss4
+@USE_DIRECTSOUND_FALSE@DIRECTSOUND_DIR =
+@USE_DIRECTSOUND_TRUE@DIRECTSOUND_DIR = directsound
+@USE_SUNAUDIO_FALSE@SUNAUDIO_DIR =
+@USE_SUNAUDIO_TRUE@SUNAUDIO_DIR = sunaudio
+@USE_OSX_AUDIO_FALSE@OSX_AUDIO_DIR =
+@USE_OSX_AUDIO_TRUE@OSX_AUDIO_DIR = osxaudio
+@USE_OSX_VIDEO_FALSE@OSX_VIDEO_DIR =
+@USE_OSX_VIDEO_TRUE@OSX_VIDEO_DIR = osxvideo
+@USE_GST_V4L2_FALSE@V4L2_DIR =
+
+# if USE_QCAM
+# QCAM_DIR=qcam
+# else
+# QCAM_DIR=
+# endif
+@USE_GST_V4L2_TRUE@V4L2_DIR = v4l2
+@USE_X_FALSE@XIMAGE_DIR =
+
+# if USE_VCD
+# VCD_DIR=vcd
+# else
+# VCD_DIR=
+# endif
+
+# if USE_CDROM
+# CDROM_DIR=cdrom
+# else
+# CDROM_DIR=
+# endif
+
+# if USE_OPENGL
+# GL_DIR=glsink
+# else
+# GL_DIR=
+# endif
+@USE_X_TRUE@XIMAGE_DIR = ximage
+SUBDIRS = $(DIRECTSOUND_DIR) $(OSS_DIR) $(OSS4_DIR) $(OSX_AUDIO_DIR) $(OSX_VIDEO_DIR) $(SUNAUDIO_DIR) $(V4L2_DIR) $(XIMAGE_DIR)
+DIST_SUBDIRS = directsound oss oss4 osxaudio osxvideo sunaudio v4l2 waveform ximage
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/common/parallel-subdirs.mak $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sys/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu sys/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+$(top_srcdir)/common/parallel-subdirs.mak:
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ ctags ctags-recursive distclean distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am
+
+
+.PHONY: independent-subdirs $(SUBDIRS)
+
+independent-subdirs: $(SUBDIRS)
+
+$(SUBDIRS):
+ $(MAKE) -C $@
+
+all-recursive: independent-subdirs
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sys/directsound/Makefile.am b/sys/directsound/Makefile.am
new file mode 100644
index 0000000..8227905
--- /dev/null
+++ b/sys/directsound/Makefile.am
@@ -0,0 +1,18 @@
+plugin_LTLIBRARIES = libgstdirectsoundsink.la
+
+libgstdirectsoundsink_la_SOURCES = gstdirectsoundsink.c gstdirectsoundplugin.c
+libgstdirectsoundsink_la_CFLAGS = \
+ $(GST_PLUGINS_BASE_CFLAGS) \
+ $(GST_BASE_CFLAGS) \
+ $(GST_CFLAGS) \
+ $(DIRECTSOUND_CFLAGS)
+libgstdirectsoundsink_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstaudio-$(GST_MAJORMINOR) -lgstinterfaces-$(GST_MAJORMINOR) \
+ $(GST_BASE_LIBS) \
+ $(GST_LIBS) \
+ $(DIRECTSOUND_LIBS)
+libgstdirectsoundsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(DIRECTSOUND_LDFLAGS)
+libgstdirectsoundsink_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = gstdirectsoundsink.h
diff --git a/sys/directsound/Makefile.in b/sys/directsound/Makefile.in
new file mode 100644
index 0000000..94cbb01
--- /dev/null
+++ b/sys/directsound/Makefile.in
@@ -0,0 +1,828 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sys/directsound
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
+ $(top_srcdir)/common/m4/as-auto-alt.m4 \
+ $(top_srcdir)/common/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/common/m4/as-gcc-inline-assembly.m4 \
+ $(top_srcdir)/common/m4/as-objc.m4 \
+ $(top_srcdir)/common/m4/as-python.m4 \
+ $(top_srcdir)/common/m4/as-scrub-include.m4 \
+ $(top_srcdir)/common/m4/as-version.m4 \
+ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
+ $(top_srcdir)/common/m4/gst-arch.m4 \
+ $(top_srcdir)/common/m4/gst-args.m4 \
+ $(top_srcdir)/common/m4/gst-check.m4 \
+ $(top_srcdir)/common/m4/gst-default.m4 \
+ $(top_srcdir)/common/m4/gst-dowhile.m4 \
+ $(top_srcdir)/common/m4/gst-error.m4 \
+ $(top_srcdir)/common/m4/gst-feature.m4 \
+ $(top_srcdir)/common/m4/gst-gettext.m4 \
+ $(top_srcdir)/common/m4/gst-glib2.m4 \
+ $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \
+ $(top_srcdir)/common/m4/gst-platform.m4 \
+ $(top_srcdir)/common/m4/gst-plugin-docs.m4 \
+ $(top_srcdir)/common/m4/gst-plugindir.m4 \
+ $(top_srcdir)/common/m4/gst-x11.m4 \
+ $(top_srcdir)/common/m4/gst.m4 \
+ $(top_srcdir)/common/m4/gtk-doc.m4 \
+ $(top_srcdir)/common/m4/orc.m4 $(top_srcdir)/common/m4/pkg.m4 \
+ $(top_srcdir)/m4/aalib.m4 $(top_srcdir)/m4/esd.m4 \
+ $(top_srcdir)/m4/gconf-2.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gst-fionread.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgstdirectsoundsink_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_libgstdirectsoundsink_la_OBJECTS = \
+ libgstdirectsoundsink_la-gstdirectsoundsink.lo \
+ libgstdirectsoundsink_la-gstdirectsoundplugin.lo
+libgstdirectsoundsink_la_OBJECTS = \
+ $(am_libgstdirectsoundsink_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libgstdirectsoundsink_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(libgstdirectsoundsink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(libgstdirectsoundsink_la_CFLAGS) \
+ $(CFLAGS) $(libgstdirectsoundsink_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libgstdirectsoundsink_la_SOURCES)
+DIST_SOURCES = $(libgstdirectsoundsink_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+AALIB_CFLAGS = @AALIB_CFLAGS@
+AALIB_CONFIG = @AALIB_CONFIG@
+AALIB_LIBS = @AALIB_LIBS@
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+ANNODEX_CFLAGS = @ANNODEX_CFLAGS@
+ANNODEX_LIBS = @ANNODEX_LIBS@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BZ2_LIBS = @BZ2_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_GOBJECT_CFLAGS = @CAIRO_GOBJECT_CFLAGS@
+CAIRO_GOBJECT_LIBS = @CAIRO_GOBJECT_LIBS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@
+DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@
+DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@
+DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@
+DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@
+DIRECTSOUND_CFLAGS = @DIRECTSOUND_CFLAGS@
+DIRECTSOUND_LDFLAGS = @DIRECTSOUND_LDFLAGS@
+DIRECTSOUND_LIBS = @DIRECTSOUND_LIBS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DV1394_CFLAGS = @DV1394_CFLAGS@
+DV1394_LIBS = @DV1394_LIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ERROR_CFLAGS = @ERROR_CFLAGS@
+ERROR_CXXFLAGS = @ERROR_CXXFLAGS@
+ESD_CFLAGS = @ESD_CFLAGS@
+ESD_CONFIG = @ESD_CONFIG@
+ESD_LIBS = @ESD_LIBS@
+EXEEXT = @EXEEXT@
+FFLAGS = @FFLAGS@
+FGREP = @FGREP@
+FLAC_CFLAGS = @FLAC_CFLAGS@
+FLAC_LIBS = @FLAC_LIBS@
+GCONFTOOL = @GCONFTOOL@
+GCONF_CFLAGS = @GCONF_CFLAGS@
+GCONF_LIBS = @GCONF_LIBS@
+GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+GCOV = @GCOV@
+GCOV_CFLAGS = @GCOV_CFLAGS@
+GCOV_LIBS = @GCOV_LIBS@
+GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@
+GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_PREFIX = @GLIB_PREFIX@
+GLIB_REQ = @GLIB_REQ@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@
+GSTPB_PREFIX = @GSTPB_PREFIX@
+GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@
+GST_BASE_CFLAGS = @GST_BASE_CFLAGS@
+GST_BASE_LIBS = @GST_BASE_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_CONTROLLER_CFLAGS = @GST_CONTROLLER_CFLAGS@
+GST_CONTROLLER_LIBS = @GST_CONTROLLER_LIBS@
+GST_CXXFLAGS = @GST_CXXFLAGS@
+GST_GDP_CFLAGS = @GST_GDP_CFLAGS@
+GST_GDP_LIBS = @GST_GDP_LIBS@
+GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@
+GST_LIBS = @GST_LIBS@
+GST_LICENSE = @GST_LICENSE@
+GST_LT_LDFLAGS = @GST_LT_LDFLAGS@
+GST_MAJORMINOR = @GST_MAJORMINOR@
+GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@
+GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@
+GST_PACKAGE_NAME = @GST_PACKAGE_NAME@
+GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@
+GST_PLUGINS_ALL = @GST_PLUGINS_ALL@
+GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@
+GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@
+GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@
+GST_PLUGINS_DIR = @GST_PLUGINS_DIR@
+GST_PLUGINS_SELECTED = @GST_PLUGINS_SELECTED@
+GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@
+GST_PREFIX = @GST_PREFIX@
+GST_TOOLS_DIR = @GST_TOOLS_DIR@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_X11_CFLAGS = @GTK_X11_CFLAGS@
+GTK_X11_LIBS = @GTK_X11_LIBS@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+HAVE_AVC1394 = @HAVE_AVC1394@
+HAVE_BZ2 = @HAVE_BZ2@
+HAVE_CXX = @HAVE_CXX@
+HAVE_DIRECTSOUND = @HAVE_DIRECTSOUND@
+HAVE_GCONFTOOL = @HAVE_GCONFTOOL@
+HAVE_ROM1394 = @HAVE_ROM1394@
+HAVE_SPEEX = @HAVE_SPEEX@
+HAVE_X = @HAVE_X@
+HAVE_XSHM = @HAVE_XSHM@
+HAVE_ZLIB = @HAVE_ZLIB@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JACK_0_120_1_CFLAGS = @JACK_0_120_1_CFLAGS@
+JACK_0_120_1_LIBS = @JACK_0_120_1_LIBS@
+JACK_1_9_7_CFLAGS = @JACK_1_9_7_CFLAGS@
+JACK_1_9_7_LIBS = @JACK_1_9_7_LIBS@
+JACK_CFLAGS = @JACK_CFLAGS@
+JACK_LIBS = @JACK_LIBS@
+JPEG_LIBS = @JPEG_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCACA_CFLAGS = @LIBCACA_CFLAGS@
+LIBCACA_LIBS = @LIBCACA_LIBS@
+LIBDV_CFLAGS = @LIBDV_CFLAGS@
+LIBDV_LIBS = @LIBDV_LIBS@
+LIBICONV = @LIBICONV@
+LIBIEC61883_CFLAGS = @LIBIEC61883_CFLAGS@
+LIBIEC61883_LIBS = @LIBIEC61883_LIBS@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBPNG_CFLAGS = @LIBPNG_CFLAGS@
+LIBPNG_LIBS = @LIBPNG_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBV4L2_CFLAGS = @LIBV4L2_CFLAGS@
+LIBV4L2_LIBS = @LIBV4L2_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCALEDIR = @LOCALEDIR@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJC_LDFLAGS = @OBJC_LDFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORCC = @ORCC@
+ORCC_FLAGS = @ORCC_FLAGS@
+ORC_CFLAGS = @ORC_CFLAGS@
+ORC_LIBS = @ORC_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@
+PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PLUGINDIR = @PLUGINDIR@
+POSUB = @POSUB@
+PROFILE_CFLAGS = @PROFILE_CFLAGS@
+PULSE_0_9_20_CFLAGS = @PULSE_0_9_20_CFLAGS@
+PULSE_0_9_20_LIBS = @PULSE_0_9_20_LIBS@
+PULSE_1_0_CFLAGS = @PULSE_1_0_CFLAGS@
+PULSE_1_0_LIBS = @PULSE_1_0_LIBS@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RAW1394_CFLAGS = @RAW1394_CFLAGS@
+RAW1394_LIBS = @RAW1394_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHOUT2_CFLAGS = @SHOUT2_CFLAGS@
+SHOUT2_LIBS = @SHOUT2_LIBS@
+SOUP_CFLAGS = @SOUP_CFLAGS@
+SOUP_LIBS = @SOUP_LIBS@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+TAGLIB_CFLAGS = @TAGLIB_CFLAGS@
+TAGLIB_CXXFLAGS = @TAGLIB_CXXFLAGS@
+TAGLIB_LIBS = @TAGLIB_LIBS@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VALGRIND_PATH = @VALGRIND_PATH@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
+WAVPACK_LIBS = @WAVPACK_LIBS@
+WIN32_LIBS = @WIN32_LIBS@
+XDAMAGE_CFLAGS = @XDAMAGE_CFLAGS@
+XDAMAGE_LIBS = @XDAMAGE_LIBS@
+XFIXES_CFLAGS = @XFIXES_CFLAGS@
+XFIXES_LIBS = @XFIXES_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+XMKMF = @XMKMF@
+XSHM_LIBS = @XSHM_LIBS@
+XVIDEO_LIBS = @XVIDEO_LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = libgstdirectsoundsink.la
+libgstdirectsoundsink_la_SOURCES = gstdirectsoundsink.c gstdirectsoundplugin.c
+libgstdirectsoundsink_la_CFLAGS = \
+ $(GST_PLUGINS_BASE_CFLAGS) \
+ $(GST_BASE_CFLAGS) \
+ $(GST_CFLAGS) \
+ $(DIRECTSOUND_CFLAGS)
+
+libgstdirectsoundsink_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstaudio-$(GST_MAJORMINOR) -lgstinterfaces-$(GST_MAJORMINOR) \
+ $(GST_BASE_LIBS) \
+ $(GST_LIBS) \
+ $(DIRECTSOUND_LIBS)
+
+libgstdirectsoundsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(DIRECTSOUND_LDFLAGS)
+libgstdirectsoundsink_la_LIBTOOLFLAGS = --tag=disable-static
+noinst_HEADERS = gstdirectsoundsink.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sys/directsound/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu sys/directsound/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgstdirectsoundsink.la: $(libgstdirectsoundsink_la_OBJECTS) $(libgstdirectsoundsink_la_DEPENDENCIES) $(EXTRA_libgstdirectsoundsink_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgstdirectsoundsink_la_LINK) -rpath $(plugindir) $(libgstdirectsoundsink_la_OBJECTS) $(libgstdirectsoundsink_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstdirectsoundsink_la-gstdirectsoundplugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstdirectsoundsink_la-gstdirectsoundsink.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libgstdirectsoundsink_la-gstdirectsoundsink.lo: gstdirectsoundsink.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstdirectsoundsink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdirectsoundsink_la_CFLAGS) $(CFLAGS) -MT libgstdirectsoundsink_la-gstdirectsoundsink.lo -MD -MP -MF $(DEPDIR)/libgstdirectsoundsink_la-gstdirectsoundsink.Tpo -c -o libgstdirectsoundsink_la-gstdirectsoundsink.lo `test -f 'gstdirectsoundsink.c' || echo '$(srcdir)/'`gstdirectsoundsink.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstdirectsoundsink_la-gstdirectsoundsink.Tpo $(DEPDIR)/libgstdirectsoundsink_la-gstdirectsoundsink.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdirectsoundsink.c' object='libgstdirectsoundsink_la-gstdirectsoundsink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstdirectsoundsink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdirectsoundsink_la_CFLAGS) $(CFLAGS) -c -o libgstdirectsoundsink_la-gstdirectsoundsink.lo `test -f 'gstdirectsoundsink.c' || echo '$(srcdir)/'`gstdirectsoundsink.c
+
+libgstdirectsoundsink_la-gstdirectsoundplugin.lo: gstdirectsoundplugin.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstdirectsoundsink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdirectsoundsink_la_CFLAGS) $(CFLAGS) -MT libgstdirectsoundsink_la-gstdirectsoundplugin.lo -MD -MP -MF $(DEPDIR)/libgstdirectsoundsink_la-gstdirectsoundplugin.Tpo -c -o libgstdirectsoundsink_la-gstdirectsoundplugin.lo `test -f 'gstdirectsoundplugin.c' || echo '$(srcdir)/'`gstdirectsoundplugin.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstdirectsoundsink_la-gstdirectsoundplugin.Tpo $(DEPDIR)/libgstdirectsoundsink_la-gstdirectsoundplugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdirectsoundplugin.c' object='libgstdirectsoundsink_la-gstdirectsoundplugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstdirectsoundsink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstdirectsoundsink_la_CFLAGS) $(CFLAGS) -c -o libgstdirectsoundsink_la-gstdirectsoundplugin.lo `test -f 'gstdirectsoundplugin.c' || echo '$(srcdir)/'`gstdirectsoundplugin.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sys/directsound/gstdirectsoundplugin.c b/sys/directsound/gstdirectsoundplugin.c
new file mode 100644
index 0000000..1af665a
--- /dev/null
+++ b/sys/directsound/gstdirectsoundplugin.c
@@ -0,0 +1,49 @@
+/* GStreamer
+* Copyright (C) 2005 Sebastien Moutte <sebastien@moutte.net>
+* Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.com>
+*
+* gstdirectsoundplugin.c:
+*
+* 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.
+*
+*
+* The development of this code was made possible due to the involvement
+* of Pioneers of the Inevitable, the creators of the Songbird Music player
+*
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstdirectsoundsink.h"
+
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ if (!gst_element_register (plugin, "directsoundsink", GST_RANK_PRIMARY,
+ GST_TYPE_DIRECTSOUND_SINK))
+ return FALSE;
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "directsound",
+ "Direct Sound plugin library",
+ plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/directsound/gstdirectsoundsink.c b/sys/directsound/gstdirectsoundsink.c
new file mode 100644
index 0000000..2f9a04c
--- /dev/null
+++ b/sys/directsound/gstdirectsoundsink.c
@@ -0,0 +1,785 @@
+/* GStreamer
+* Copyright (C) 2005 Sebastien Moutte <sebastien@moutte.net>
+* Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.com>
+* Copyright (C) 2010 Fluendo S.A. <support@fluendo.com>
+*
+* gstdirectsoundsink.c:
+*
+* 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.
+*
+*
+* The development of this code was made possible due to the involvement
+* of Pioneers of the Inevitable, the creators of the Songbird Music player
+*
+*/
+
+/**
+ * SECTION:element-directsoundsink
+ *
+ * This element lets you output sound using the DirectSound API.
+ *
+ * Note that you should almost always use generic audio conversion elements
+ * like audioconvert and audioresample in front of an audiosink to make sure
+ * your pipeline works under all circumstances (those conversion elements will
+ * act in passthrough-mode if no conversion is necessary).
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * |[
+ * gst-launch -v audiotestsrc ! audioconvert ! volume volume=0.1 ! directsoundsink
+ * ]| will output a sine wave (continuous beep sound) to your sound card (with
+ * a very low volume as precaution).
+ * |[
+ * gst-launch -v filesrc location=music.ogg ! decodebin ! audioconvert ! audioresample ! directsoundsink
+ * ]| will play an Ogg/Vorbis audio file and output it.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstdirectsoundsink.h"
+
+#include <math.h>
+
+#ifdef __CYGWIN__
+#include <unistd.h>
+#ifndef _swab
+#define _swab swab
+#endif
+#endif
+
+GST_DEBUG_CATEGORY_STATIC (directsoundsink_debug);
+#define GST_CAT_DEFAULT directsoundsink_debug
+
+static void gst_directsound_sink_finalise (GObject * object);
+
+static void gst_directsound_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_directsound_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static GstCaps *gst_directsound_sink_getcaps (GstBaseSink * bsink);
+static gboolean gst_directsound_sink_prepare (GstAudioSink * asink,
+ GstRingBufferSpec * spec);
+static gboolean gst_directsound_sink_unprepare (GstAudioSink * asink);
+
+static gboolean gst_directsound_sink_open (GstAudioSink * asink);
+static gboolean gst_directsound_sink_close (GstAudioSink * asink);
+static guint gst_directsound_sink_write (GstAudioSink * asink, gpointer data,
+ guint length);
+static guint gst_directsound_sink_delay (GstAudioSink * asink);
+static void gst_directsound_sink_reset (GstAudioSink * asink);
+static GstCaps *gst_directsound_probe_supported_formats (GstDirectSoundSink *
+ dsoundsink, const GstCaps * template_caps);
+
+/* interfaces */
+static void gst_directsound_sink_interfaces_init (GType type);
+static void
+gst_directsound_sink_implements_interface_init (GstImplementsInterfaceClass *
+ iface);
+static void gst_directsound_sink_mixer_interface_init (GstMixerClass * iface);
+
+static GstStaticPadTemplate directsoundsink_sink_factory =
+ GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-int, "
+ "signed = (boolean) TRUE, "
+ "width = (int) 16, "
+ "depth = (int) 16, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
+ "audio/x-raw-int, "
+ "signed = (boolean) FALSE, "
+ "width = (int) 8, "
+ "depth = (int) 8, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ];"
+ "audio/x-iec958"));
+
+enum
+{
+ PROP_0,
+ PROP_VOLUME
+};
+
+GST_BOILERPLATE_FULL (GstDirectSoundSink, gst_directsound_sink, GstAudioSink,
+ GST_TYPE_AUDIO_SINK, gst_directsound_sink_interfaces_init);
+
+/* interfaces stuff */
+static void
+gst_directsound_sink_interfaces_init (GType type)
+{
+ static const GInterfaceInfo implements_interface_info = {
+ (GInterfaceInitFunc) gst_directsound_sink_implements_interface_init,
+ NULL,
+ NULL,
+ };
+
+ static const GInterfaceInfo mixer_interface_info = {
+ (GInterfaceInitFunc) gst_directsound_sink_mixer_interface_init,
+ NULL,
+ NULL,
+ };
+
+ g_type_add_interface_static (type,
+ GST_TYPE_IMPLEMENTS_INTERFACE, &implements_interface_info);
+ g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_interface_info);
+}
+
+static gboolean
+gst_directsound_sink_interface_supported (GstImplementsInterface * iface,
+ GType iface_type)
+{
+ g_return_val_if_fail (iface_type == GST_TYPE_MIXER, FALSE);
+
+ /* for the sake of this example, we'll always support it. However, normally,
+ * you would check whether the device you've opened supports mixers. */
+ return TRUE;
+}
+
+static void
+gst_directsound_sink_implements_interface_init (GstImplementsInterfaceClass *
+ iface)
+{
+ iface->supported = gst_directsound_sink_interface_supported;
+}
+
+/*
+ * This function returns the list of support tracks (inputs, outputs)
+ * on this element instance. Elements usually build this list during
+ * _init () or when going from NULL to READY.
+ */
+
+static const GList *
+gst_directsound_sink_mixer_list_tracks (GstMixer * mixer)
+{
+ GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (mixer);
+
+ return dsoundsink->tracks;
+}
+
+static void
+gst_directsound_sink_set_volume (GstDirectSoundSink * dsoundsink)
+{
+ if (dsoundsink->pDSBSecondary) {
+ /* DirectSound controls volume using units of 100th of a decibel,
+ * ranging from -10000 to 0. We use a linear scale of 0 - 100
+ * here, so remap.
+ */
+ long dsVolume;
+ if (dsoundsink->volume == 0)
+ dsVolume = -10000;
+ else
+ dsVolume = 100 * (long) (20 * log10 ((double) dsoundsink->volume / 100.));
+ dsVolume = CLAMP (dsVolume, -10000, 0);
+
+ GST_DEBUG_OBJECT (dsoundsink,
+ "Setting volume on secondary buffer to %d from %d", (int) dsVolume,
+ (int) dsoundsink->volume);
+ IDirectSoundBuffer_SetVolume (dsoundsink->pDSBSecondary, dsVolume);
+ }
+}
+
+/*
+ * Set volume. volumes is an array of size track->num_channels, and
+ * each value in the array gives the wanted volume for one channel
+ * on the track.
+ */
+
+static void
+gst_directsound_sink_mixer_set_volume (GstMixer * mixer,
+ GstMixerTrack * track, gint * volumes)
+{
+ GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (mixer);
+
+ if (volumes[0] != dsoundsink->volume) {
+ dsoundsink->volume = volumes[0];
+
+ gst_directsound_sink_set_volume (dsoundsink);
+ }
+}
+
+static void
+gst_directsound_sink_mixer_get_volume (GstMixer * mixer,
+ GstMixerTrack * track, gint * volumes)
+{
+ GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (mixer);
+
+ volumes[0] = dsoundsink->volume;
+}
+
+static void
+gst_directsound_sink_mixer_interface_init (GstMixerClass * iface)
+{
+ /* the mixer interface requires a definition of the mixer type:
+ * hardware or software? */
+ GST_MIXER_TYPE (iface) = GST_MIXER_SOFTWARE;
+
+ /* virtual function pointers */
+ iface->list_tracks = gst_directsound_sink_mixer_list_tracks;
+ iface->set_volume = gst_directsound_sink_mixer_set_volume;
+ iface->get_volume = gst_directsound_sink_mixer_get_volume;
+}
+
+static void
+gst_directsound_sink_finalise (GObject * object)
+{
+ GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (object);
+
+ g_mutex_free (dsoundsink->dsound_lock);
+
+ if (dsoundsink->tracks) {
+ g_list_foreach (dsoundsink->tracks, (GFunc) g_object_unref, NULL);
+ g_list_free (dsoundsink->tracks);
+ dsoundsink->tracks = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_directsound_sink_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_set_details_simple (element_class,
+ "Direct Sound Audio Sink", "Sink/Audio",
+ "Output to a sound card via Direct Sound",
+ "Sebastien Moutte <sebastien@moutte.net>");
+ gst_element_class_add_static_pad_template (element_class,
+ &directsoundsink_sink_factory);
+}
+
+static void
+gst_directsound_sink_class_init (GstDirectSoundSinkClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSinkClass *gstbasesink_class;
+ GstBaseAudioSinkClass *gstbaseaudiosink_class;
+ GstAudioSinkClass *gstaudiosink_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesink_class = (GstBaseSinkClass *) klass;
+ gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
+ gstaudiosink_class = (GstAudioSinkClass *) klass;
+
+ GST_DEBUG_CATEGORY_INIT (directsoundsink_debug, "directsoundsink", 0,
+ "DirectSound sink");
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = gst_directsound_sink_finalise;
+ gobject_class->set_property = gst_directsound_sink_set_property;
+ gobject_class->get_property = gst_directsound_sink_get_property;
+
+ gstbasesink_class->get_caps =
+ GST_DEBUG_FUNCPTR (gst_directsound_sink_getcaps);
+
+ gstaudiosink_class->prepare =
+ GST_DEBUG_FUNCPTR (gst_directsound_sink_prepare);
+ gstaudiosink_class->unprepare =
+ GST_DEBUG_FUNCPTR (gst_directsound_sink_unprepare);
+ gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_directsound_sink_open);
+ gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_directsound_sink_close);
+ gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_directsound_sink_write);
+ gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_directsound_sink_delay);
+ gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_directsound_sink_reset);
+
+ g_object_class_install_property (gobject_class,
+ PROP_VOLUME,
+ g_param_spec_double ("volume", "Volume",
+ "Volume of this stream", 0.0, 1.0, 1.0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+gst_directsound_sink_init (GstDirectSoundSink * dsoundsink,
+ GstDirectSoundSinkClass * g_class)
+{
+ GstMixerTrack *track = NULL;
+
+ dsoundsink->tracks = NULL;
+ track = g_object_new (GST_TYPE_MIXER_TRACK, NULL);
+ track->label = g_strdup ("DSoundTrack");
+ track->num_channels = 2;
+ track->min_volume = 0;
+ track->max_volume = 100;
+ track->flags = GST_MIXER_TRACK_OUTPUT;
+ dsoundsink->tracks = g_list_append (dsoundsink->tracks, track);
+
+ dsoundsink->pDS = NULL;
+ dsoundsink->cached_caps = NULL;
+ dsoundsink->pDSBSecondary = NULL;
+ dsoundsink->current_circular_offset = 0;
+ dsoundsink->buffer_size = DSBSIZE_MIN;
+ dsoundsink->volume = 100;
+ dsoundsink->dsound_lock = g_mutex_new ();
+ dsoundsink->first_buffer_after_reset = FALSE;
+}
+
+static void
+gst_directsound_sink_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ GstDirectSoundSink *sink = GST_DIRECTSOUND_SINK (object);
+
+ switch (prop_id) {
+ case PROP_VOLUME:
+ sink->volume = (int) (g_value_get_double (value) * 100);
+ gst_directsound_sink_set_volume (sink);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_directsound_sink_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ GstDirectSoundSink *sink = GST_DIRECTSOUND_SINK (object);
+
+ switch (prop_id) {
+ case PROP_VOLUME:
+ g_value_set_double (value, (double) sink->volume / 100.);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstCaps *
+gst_directsound_sink_getcaps (GstBaseSink * bsink)
+{
+ GstElementClass *element_class;
+ GstPadTemplate *pad_template;
+ GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (bsink);
+ GstCaps *caps;
+ gchar *caps_string = NULL;
+
+ if (dsoundsink->pDS == NULL) {
+ GST_DEBUG_OBJECT (dsoundsink, "device not open, using template caps");
+ return NULL; /* base class will get template caps for us */
+ }
+
+ if (dsoundsink->cached_caps) {
+ caps_string = gst_caps_to_string (dsoundsink->cached_caps);
+ GST_DEBUG_OBJECT (dsoundsink, "Returning cached caps: %s", caps_string);
+ g_free (caps_string);
+ return gst_caps_ref (dsoundsink->cached_caps);
+ }
+
+ element_class = GST_ELEMENT_GET_CLASS (dsoundsink);
+ pad_template = gst_element_class_get_pad_template (element_class, "sink");
+ g_return_val_if_fail (pad_template != NULL, NULL);
+
+ caps = gst_directsound_probe_supported_formats (dsoundsink,
+ gst_pad_template_get_caps (pad_template));
+ if (caps) {
+ dsoundsink->cached_caps = gst_caps_ref (caps);
+ }
+
+ if (caps) {
+ gchar *caps_string = gst_caps_to_string (caps);
+ GST_DEBUG_OBJECT (dsoundsink, "returning caps %s", caps_string);
+ g_free (caps_string);
+ }
+
+ return caps;
+}
+
+static gboolean
+gst_directsound_sink_open (GstAudioSink * asink)
+{
+ GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (asink);
+ HRESULT hRes;
+
+ /* create and initialize a DirecSound object */
+ if (FAILED (hRes = DirectSoundCreate (NULL, &dsoundsink->pDS, NULL))) {
+ GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ,
+ ("gst_directsound_sink_open: DirectSoundCreate: %s",
+ DXGetErrorString9 (hRes)), (NULL));
+ return FALSE;
+ }
+
+ if (FAILED (hRes = IDirectSound_SetCooperativeLevel (dsoundsink->pDS,
+ GetDesktopWindow (), DSSCL_PRIORITY))) {
+ GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ,
+ ("gst_directsound_sink_open: IDirectSound_SetCooperativeLevel: %s",
+ DXGetErrorString9 (hRes)), (NULL));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_directsound_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
+{
+ GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (asink);
+ HRESULT hRes;
+ DSBUFFERDESC descSecondary;
+ WAVEFORMATEX wfx;
+
+ /*save number of bytes per sample and buffer format */
+ dsoundsink->bytes_per_sample = spec->bytes_per_sample;
+ dsoundsink->buffer_format = spec->format;
+
+ /* fill the WAVEFORMATEX structure with spec params */
+ memset (&wfx, 0, sizeof (wfx));
+ if (spec->format != GST_IEC958) {
+ wfx.cbSize = sizeof (wfx);
+ wfx.wFormatTag = WAVE_FORMAT_PCM;
+ wfx.nChannels = spec->channels;
+ wfx.nSamplesPerSec = spec->rate;
+ wfx.wBitsPerSample = (spec->bytes_per_sample * 8) / wfx.nChannels;
+ wfx.nBlockAlign = spec->bytes_per_sample;
+ wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+
+ /* Create directsound buffer with size based on our configured
+ * buffer_size (which is 200 ms by default) */
+ dsoundsink->buffer_size =
+ gst_util_uint64_scale_int (wfx.nAvgBytesPerSec, spec->buffer_time,
+ GST_MSECOND);
+ /* Make sure we make those numbers multiple of our sample size in bytes */
+ dsoundsink->buffer_size += dsoundsink->buffer_size % spec->bytes_per_sample;
+
+ spec->segsize =
+ gst_util_uint64_scale_int (wfx.nAvgBytesPerSec, spec->latency_time,
+ GST_MSECOND);
+ spec->segsize += spec->segsize % spec->bytes_per_sample;
+ spec->segtotal = dsoundsink->buffer_size / spec->segsize;
+ } else {
+#ifdef WAVE_FORMAT_DOLBY_AC3_SPDIF
+ wfx.cbSize = 0;
+ wfx.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
+ wfx.nChannels = 2;
+ wfx.nSamplesPerSec = spec->rate;
+ wfx.wBitsPerSample = 16;
+ wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
+ wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+
+ spec->segsize = 6144;
+ spec->segtotal = 10;
+#else
+ g_assert_not_reached ();
+#endif
+ }
+
+ // Make the final buffer size be an integer number of segments
+ dsoundsink->buffer_size = spec->segsize * spec->segtotal;
+
+ GST_INFO_OBJECT (dsoundsink,
+ "GstRingBufferSpec->channels: %d, GstRingBufferSpec->rate: %d, GstRingBufferSpec->bytes_per_sample: %d\n"
+ "WAVEFORMATEX.nSamplesPerSec: %ld, WAVEFORMATEX.wBitsPerSample: %d, WAVEFORMATEX.nBlockAlign: %d, WAVEFORMATEX.nAvgBytesPerSec: %ld\n"
+ "Size of dsound circular buffer=>%d\n", spec->channels, spec->rate,
+ spec->bytes_per_sample, wfx.nSamplesPerSec, wfx.wBitsPerSample,
+ wfx.nBlockAlign, wfx.nAvgBytesPerSec, dsoundsink->buffer_size);
+
+ /* create a secondary directsound buffer */
+ memset (&descSecondary, 0, sizeof (DSBUFFERDESC));
+ descSecondary.dwSize = sizeof (DSBUFFERDESC);
+ descSecondary.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS;
+ if (spec->format != GST_IEC958)
+ descSecondary.dwFlags |= DSBCAPS_CTRLVOLUME;
+
+ descSecondary.dwBufferBytes = dsoundsink->buffer_size;
+ descSecondary.lpwfxFormat = (WAVEFORMATEX *) & wfx;
+
+ hRes = IDirectSound_CreateSoundBuffer (dsoundsink->pDS, &descSecondary,
+ &dsoundsink->pDSBSecondary, NULL);
+ if (FAILED (hRes)) {
+ GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ,
+ ("gst_directsound_sink_prepare: IDirectSound_CreateSoundBuffer: %s",
+ DXGetErrorString9 (hRes)), (NULL));
+ return FALSE;
+ }
+
+ gst_directsound_sink_set_volume (dsoundsink);
+
+ return TRUE;
+}
+
+static gboolean
+gst_directsound_sink_unprepare (GstAudioSink * asink)
+{
+ GstDirectSoundSink *dsoundsink;
+
+ dsoundsink = GST_DIRECTSOUND_SINK (asink);
+
+ /* release secondary DirectSound buffer */
+ if (dsoundsink->pDSBSecondary) {
+ IDirectSoundBuffer_Release (dsoundsink->pDSBSecondary);
+ dsoundsink->pDSBSecondary = NULL;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_directsound_sink_close (GstAudioSink * asink)
+{
+ GstDirectSoundSink *dsoundsink = NULL;
+
+ dsoundsink = GST_DIRECTSOUND_SINK (asink);
+
+ /* release DirectSound object */
+ g_return_val_if_fail (dsoundsink->pDS != NULL, FALSE);
+ IDirectSound_Release (dsoundsink->pDS);
+ dsoundsink->pDS = NULL;
+
+ gst_caps_replace (&dsoundsink->cached_caps, NULL);
+
+ return TRUE;
+}
+
+static guint
+gst_directsound_sink_write (GstAudioSink * asink, gpointer data, guint length)
+{
+ GstDirectSoundSink *dsoundsink;
+ DWORD dwStatus;
+ HRESULT hRes;
+ LPVOID pLockedBuffer1 = NULL, pLockedBuffer2 = NULL;
+ DWORD dwSizeBuffer1, dwSizeBuffer2;
+ DWORD dwCurrentPlayCursor;
+
+ dsoundsink = GST_DIRECTSOUND_SINK (asink);
+
+ /* Fix endianness */
+ if (dsoundsink->buffer_format == GST_IEC958)
+ _swab (data, data, length);
+
+ GST_DSOUND_LOCK (dsoundsink);
+
+ /* get current buffer status */
+ hRes = IDirectSoundBuffer_GetStatus (dsoundsink->pDSBSecondary, &dwStatus);
+
+ /* get current play cursor position */
+ hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary,
+ &dwCurrentPlayCursor, NULL);
+
+ if (SUCCEEDED (hRes) && (dwStatus & DSBSTATUS_PLAYING)) {
+ DWORD dwFreeBufferSize;
+
+ calculate_freesize:
+ /* calculate the free size of the circular buffer */
+ if (dwCurrentPlayCursor < dsoundsink->current_circular_offset)
+ dwFreeBufferSize =
+ dsoundsink->buffer_size - (dsoundsink->current_circular_offset -
+ dwCurrentPlayCursor);
+ else
+ dwFreeBufferSize =
+ dwCurrentPlayCursor - dsoundsink->current_circular_offset;
+
+ if (length >= dwFreeBufferSize) {
+ Sleep (100);
+ hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary,
+ &dwCurrentPlayCursor, NULL);
+
+ hRes =
+ IDirectSoundBuffer_GetStatus (dsoundsink->pDSBSecondary, &dwStatus);
+ if (SUCCEEDED (hRes) && (dwStatus & DSBSTATUS_PLAYING))
+ goto calculate_freesize;
+ else {
+ dsoundsink->first_buffer_after_reset = FALSE;
+ GST_DSOUND_UNLOCK (dsoundsink);
+ return 0;
+ }
+ }
+ }
+
+ if (dwStatus & DSBSTATUS_BUFFERLOST) {
+ hRes = IDirectSoundBuffer_Restore (dsoundsink->pDSBSecondary); /*need a loop waiting the buffer is restored?? */
+
+ dsoundsink->current_circular_offset = 0;
+ }
+
+ hRes = IDirectSoundBuffer_Lock (dsoundsink->pDSBSecondary,
+ dsoundsink->current_circular_offset, length, &pLockedBuffer1,
+ &dwSizeBuffer1, &pLockedBuffer2, &dwSizeBuffer2, 0L);
+
+ if (SUCCEEDED (hRes)) {
+ // Write to pointers without reordering.
+ memcpy (pLockedBuffer1, data, dwSizeBuffer1);
+ if (pLockedBuffer2 != NULL)
+ memcpy (pLockedBuffer2, (LPBYTE) data + dwSizeBuffer1, dwSizeBuffer2);
+
+ // Update where the buffer will lock (for next time)
+ dsoundsink->current_circular_offset += dwSizeBuffer1 + dwSizeBuffer2;
+ dsoundsink->current_circular_offset %= dsoundsink->buffer_size; /* Circular buffer */
+
+ hRes = IDirectSoundBuffer_Unlock (dsoundsink->pDSBSecondary, pLockedBuffer1,
+ dwSizeBuffer1, pLockedBuffer2, dwSizeBuffer2);
+ }
+
+ /* if the buffer was not in playing state yet, call play on the buffer
+ except if this buffer is the fist after a reset (base class call reset and write a buffer when setting the sink to pause) */
+ if (!(dwStatus & DSBSTATUS_PLAYING) &&
+ dsoundsink->first_buffer_after_reset == FALSE) {
+ hRes = IDirectSoundBuffer_Play (dsoundsink->pDSBSecondary, 0, 0,
+ DSBPLAY_LOOPING);
+ }
+
+ dsoundsink->first_buffer_after_reset = FALSE;
+
+ GST_DSOUND_UNLOCK (dsoundsink);
+
+ return length;
+}
+
+static guint
+gst_directsound_sink_delay (GstAudioSink * asink)
+{
+ GstDirectSoundSink *dsoundsink;
+ HRESULT hRes;
+ DWORD dwCurrentPlayCursor;
+ DWORD dwBytesInQueue = 0;
+ gint nNbSamplesInQueue = 0;
+ DWORD dwStatus;
+
+ dsoundsink = GST_DIRECTSOUND_SINK (asink);
+
+ /* get current buffer status */
+ hRes = IDirectSoundBuffer_GetStatus (dsoundsink->pDSBSecondary, &dwStatus);
+
+ if (dwStatus & DSBSTATUS_PLAYING) {
+ /*evaluate the number of samples in queue in the circular buffer */
+ hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary,
+ &dwCurrentPlayCursor, NULL);
+
+ if (hRes == S_OK) {
+ if (dwCurrentPlayCursor < dsoundsink->current_circular_offset)
+ dwBytesInQueue =
+ dsoundsink->current_circular_offset - dwCurrentPlayCursor;
+ else
+ dwBytesInQueue =
+ dsoundsink->current_circular_offset + (dsoundsink->buffer_size -
+ dwCurrentPlayCursor);
+
+ nNbSamplesInQueue = dwBytesInQueue / dsoundsink->bytes_per_sample;
+ }
+ }
+
+ return nNbSamplesInQueue;
+}
+
+static void
+gst_directsound_sink_reset (GstAudioSink * asink)
+{
+ GstDirectSoundSink *dsoundsink;
+ LPVOID pLockedBuffer = NULL;
+ DWORD dwSizeBuffer = 0;
+
+ dsoundsink = GST_DIRECTSOUND_SINK (asink);
+
+ GST_DSOUND_LOCK (dsoundsink);
+
+ if (dsoundsink->pDSBSecondary) {
+ /*stop playing */
+ HRESULT hRes = IDirectSoundBuffer_Stop (dsoundsink->pDSBSecondary);
+
+ /*reset position */
+ hRes = IDirectSoundBuffer_SetCurrentPosition (dsoundsink->pDSBSecondary, 0);
+ dsoundsink->current_circular_offset = 0;
+
+ /*reset the buffer */
+ hRes = IDirectSoundBuffer_Lock (dsoundsink->pDSBSecondary,
+ dsoundsink->current_circular_offset, dsoundsink->buffer_size,
+ &pLockedBuffer, &dwSizeBuffer, NULL, NULL, 0L);
+
+ if (SUCCEEDED (hRes)) {
+ memset (pLockedBuffer, 0, dwSizeBuffer);
+
+ hRes =
+ IDirectSoundBuffer_Unlock (dsoundsink->pDSBSecondary, pLockedBuffer,
+ dwSizeBuffer, NULL, 0);
+ }
+ }
+
+ dsoundsink->first_buffer_after_reset = TRUE;
+
+ GST_DSOUND_UNLOCK (dsoundsink);
+}
+
+/*
+ * gst_directsound_probe_supported_formats:
+ *
+ * Takes the template caps and returns the subset which is actually
+ * supported by this device.
+ *
+ */
+
+static GstCaps *
+gst_directsound_probe_supported_formats (GstDirectSoundSink * dsoundsink,
+ const GstCaps * template_caps)
+{
+ HRESULT hRes;
+ DSBUFFERDESC descSecondary;
+ WAVEFORMATEX wfx;
+ GstCaps *caps;
+
+ caps = gst_caps_copy (template_caps);
+
+ /*
+ * Check availability of digital output by trying to create an SPDIF buffer
+ */
+
+#ifdef WAVE_FORMAT_DOLBY_AC3_SPDIF
+ /* fill the WAVEFORMATEX structure with some standard AC3 over SPDIF params */
+ memset (&wfx, 0, sizeof (wfx));
+ wfx.cbSize = 0;
+ wfx.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
+ wfx.nChannels = 2;
+ wfx.nSamplesPerSec = 48000;
+ wfx.wBitsPerSample = 16;
+ wfx.nBlockAlign = 4;
+ wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+
+ // create a secondary directsound buffer
+ memset (&descSecondary, 0, sizeof (DSBUFFERDESC));
+ descSecondary.dwSize = sizeof (DSBUFFERDESC);
+ descSecondary.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS;
+ descSecondary.dwBufferBytes = 6144;
+ descSecondary.lpwfxFormat = &wfx;
+
+ hRes = IDirectSound_CreateSoundBuffer (dsoundsink->pDS, &descSecondary,
+ &dsoundsink->pDSBSecondary, NULL);
+ if (FAILED (hRes)) {
+ GST_INFO_OBJECT (dsoundsink, "AC3 passthrough not supported "
+ "(IDirectSound_CreateSoundBuffer returned: %s)\n",
+ DXGetErrorString9 (hRes));
+ caps =
+ gst_caps_subtract (caps, gst_caps_new_simple ("audio/x-iec958", NULL));
+ } else {
+ GST_INFO_OBJECT (dsoundsink, "AC3 passthrough supported");
+ hRes = IDirectSoundBuffer_Release (dsoundsink->pDSBSecondary);
+ if (FAILED (hRes)) {
+ GST_DEBUG_OBJECT (dsoundsink,
+ "(IDirectSoundBuffer_Release returned: %s)\n",
+ DXGetErrorString9 (hRes));
+ }
+ }
+#else
+ caps = gst_caps_subtract (caps, gst_caps_new_simple ("audio/x-iec958", NULL));
+#endif
+
+ return caps;
+}
diff --git a/sys/directsound/gstdirectsoundsink.h b/sys/directsound/gstdirectsoundsink.h
new file mode 100644
index 0000000..8bb10bf
--- /dev/null
+++ b/sys/directsound/gstdirectsoundsink.h
@@ -0,0 +1,97 @@
+/* GStreamer
+ * Copyright (C) 2005 Sebastien Moutte <sebastien@moutte.net>
+ * Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.com>
+ * Copyright (C) 2010 Fluendo S.A. <support@fluendo.com>
+ *
+ * gstdirectsoundsink.h:
+ *
+ * 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.
+ *
+ * The development of this code was made possible due to the involvement
+ * of Pioneers of the Inevitable, the creators of the Songbird Music player
+ *
+ *
+ */
+
+#ifndef __GST_DIRECTSOUNDSINK_H__
+#define __GST_DIRECTSOUNDSINK_H__
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosink.h>
+#include <gst/interfaces/mixer.h>
+
+#include <windows.h>
+#include <dxerr9.h>
+#include <dsound.h>
+#include <mmreg.h>
+#include <ks.h>
+#include <ksmedia.h>
+
+G_BEGIN_DECLS
+#define GST_TYPE_DIRECTSOUND_SINK (gst_directsound_sink_get_type())
+#define GST_DIRECTSOUND_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DIRECTSOUND_SINK,GstDirectSoundSink))
+#define GST_DIRECTSOUND_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DIRECTSOUND_SINK,GstDirectSoundSinkClass))
+#define GST_IS_DIRECTSOUND_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DIRECTSOUND_SINK))
+#define GST_IS_DIRECTSOUND_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DIRECTSOUND_SINK))
+typedef struct _GstDirectSoundSink GstDirectSoundSink;
+typedef struct _GstDirectSoundSinkClass GstDirectSoundSinkClass;
+
+#define GST_DSOUND_LOCK(obj) (g_mutex_lock (obj->dsound_lock))
+#define GST_DSOUND_UNLOCK(obj) (g_mutex_unlock (obj->dsound_lock))
+
+struct _GstDirectSoundSink
+{
+ GstAudioSink sink;
+
+ /* directsound object interface pointer */
+ LPDIRECTSOUND pDS;
+
+ /* directsound sound object interface pointer */
+ LPDIRECTSOUNDBUFFER pDSBSecondary;
+
+ /* directSound buffer size */
+ guint buffer_size;
+
+ /* offset of the circular buffer where we must write next */
+ guint current_circular_offset;
+
+ guint bytes_per_sample;
+
+ /* current volume setup by mixer interface */
+ glong volume;
+
+ /* tracks list of our mixer interface implementation */
+ GList *tracks;
+
+ GstCaps *cached_caps;
+
+ /* lock used to protect writes and resets */
+ GMutex *dsound_lock;
+
+ gboolean first_buffer_after_reset;
+
+ GstBufferFormat buffer_format;
+};
+
+struct _GstDirectSoundSinkClass
+{
+ GstAudioSinkClass parent_class;
+};
+
+GType gst_directsound_sink_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_DIRECTSOUNDSINK_H__ */
diff --git a/sys/oss/Makefile.am b/sys/oss/Makefile.am
new file mode 100644
index 0000000..c42dfea
--- /dev/null
+++ b/sys/oss/Makefile.am
@@ -0,0 +1,28 @@
+plugin_LTLIBRARIES = libgstossaudio.la
+
+libgstossaudio_la_SOURCES = gstossaudio.c \
+ gstosshelper.c \
+ gstossmixer.c \
+ gstossmixerelement.c \
+ gstossmixertrack.c \
+ gstosssink.c \
+ gstosssrc.c
+
+libgstossaudio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
+libgstossaudio_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstinterfaces-$(GST_MAJORMINOR) \
+ -lgstaudio-$(GST_MAJORMINOR) \
+ $(GST_BASE_LIBS) \
+ $(GST_LIBS)
+libgstossaudio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstossaudio_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = common.h \
+ gstosssink.h \
+ gstosssrc.h \
+ gstosshelper.h \
+ gstossdmabuffer.h \
+ gstossmixer.h \
+ gstossmixerelement.h \
+ gstossmixertrack.h
diff --git a/sys/oss/Makefile.in b/sys/oss/Makefile.in
new file mode 100644
index 0000000..ce15b09
--- /dev/null
+++ b/sys/oss/Makefile.in
@@ -0,0 +1,879 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sys/oss
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
+ $(top_srcdir)/common/m4/as-auto-alt.m4 \
+ $(top_srcdir)/common/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/common/m4/as-gcc-inline-assembly.m4 \
+ $(top_srcdir)/common/m4/as-objc.m4 \
+ $(top_srcdir)/common/m4/as-python.m4 \
+ $(top_srcdir)/common/m4/as-scrub-include.m4 \
+ $(top_srcdir)/common/m4/as-version.m4 \
+ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
+ $(top_srcdir)/common/m4/gst-arch.m4 \
+ $(top_srcdir)/common/m4/gst-args.m4 \
+ $(top_srcdir)/common/m4/gst-check.m4 \
+ $(top_srcdir)/common/m4/gst-default.m4 \
+ $(top_srcdir)/common/m4/gst-dowhile.m4 \
+ $(top_srcdir)/common/m4/gst-error.m4 \
+ $(top_srcdir)/common/m4/gst-feature.m4 \
+ $(top_srcdir)/common/m4/gst-gettext.m4 \
+ $(top_srcdir)/common/m4/gst-glib2.m4 \
+ $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \
+ $(top_srcdir)/common/m4/gst-platform.m4 \
+ $(top_srcdir)/common/m4/gst-plugin-docs.m4 \
+ $(top_srcdir)/common/m4/gst-plugindir.m4 \
+ $(top_srcdir)/common/m4/gst-x11.m4 \
+ $(top_srcdir)/common/m4/gst.m4 \
+ $(top_srcdir)/common/m4/gtk-doc.m4 \
+ $(top_srcdir)/common/m4/orc.m4 $(top_srcdir)/common/m4/pkg.m4 \
+ $(top_srcdir)/m4/aalib.m4 $(top_srcdir)/m4/esd.m4 \
+ $(top_srcdir)/m4/gconf-2.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gst-fionread.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgstossaudio_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libgstossaudio_la_OBJECTS = libgstossaudio_la-gstossaudio.lo \
+ libgstossaudio_la-gstosshelper.lo \
+ libgstossaudio_la-gstossmixer.lo \
+ libgstossaudio_la-gstossmixerelement.lo \
+ libgstossaudio_la-gstossmixertrack.lo \
+ libgstossaudio_la-gstosssink.lo libgstossaudio_la-gstosssrc.lo
+libgstossaudio_la_OBJECTS = $(am_libgstossaudio_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libgstossaudio_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
+ $(CCLD) $(libgstossaudio_la_CFLAGS) $(CFLAGS) \
+ $(libgstossaudio_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libgstossaudio_la_SOURCES)
+DIST_SOURCES = $(libgstossaudio_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+AALIB_CFLAGS = @AALIB_CFLAGS@
+AALIB_CONFIG = @AALIB_CONFIG@
+AALIB_LIBS = @AALIB_LIBS@
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+ANNODEX_CFLAGS = @ANNODEX_CFLAGS@
+ANNODEX_LIBS = @ANNODEX_LIBS@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BZ2_LIBS = @BZ2_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_GOBJECT_CFLAGS = @CAIRO_GOBJECT_CFLAGS@
+CAIRO_GOBJECT_LIBS = @CAIRO_GOBJECT_LIBS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@
+DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@
+DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@
+DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@
+DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@
+DIRECTSOUND_CFLAGS = @DIRECTSOUND_CFLAGS@
+DIRECTSOUND_LDFLAGS = @DIRECTSOUND_LDFLAGS@
+DIRECTSOUND_LIBS = @DIRECTSOUND_LIBS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DV1394_CFLAGS = @DV1394_CFLAGS@
+DV1394_LIBS = @DV1394_LIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ERROR_CFLAGS = @ERROR_CFLAGS@
+ERROR_CXXFLAGS = @ERROR_CXXFLAGS@
+ESD_CFLAGS = @ESD_CFLAGS@
+ESD_CONFIG = @ESD_CONFIG@
+ESD_LIBS = @ESD_LIBS@
+EXEEXT = @EXEEXT@
+FFLAGS = @FFLAGS@
+FGREP = @FGREP@
+FLAC_CFLAGS = @FLAC_CFLAGS@
+FLAC_LIBS = @FLAC_LIBS@
+GCONFTOOL = @GCONFTOOL@
+GCONF_CFLAGS = @GCONF_CFLAGS@
+GCONF_LIBS = @GCONF_LIBS@
+GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+GCOV = @GCOV@
+GCOV_CFLAGS = @GCOV_CFLAGS@
+GCOV_LIBS = @GCOV_LIBS@
+GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@
+GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_PREFIX = @GLIB_PREFIX@
+GLIB_REQ = @GLIB_REQ@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@
+GSTPB_PREFIX = @GSTPB_PREFIX@
+GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@
+GST_BASE_CFLAGS = @GST_BASE_CFLAGS@
+GST_BASE_LIBS = @GST_BASE_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_CONTROLLER_CFLAGS = @GST_CONTROLLER_CFLAGS@
+GST_CONTROLLER_LIBS = @GST_CONTROLLER_LIBS@
+GST_CXXFLAGS = @GST_CXXFLAGS@
+GST_GDP_CFLAGS = @GST_GDP_CFLAGS@
+GST_GDP_LIBS = @GST_GDP_LIBS@
+GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@
+GST_LIBS = @GST_LIBS@
+GST_LICENSE = @GST_LICENSE@
+GST_LT_LDFLAGS = @GST_LT_LDFLAGS@
+GST_MAJORMINOR = @GST_MAJORMINOR@
+GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@
+GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@
+GST_PACKAGE_NAME = @GST_PACKAGE_NAME@
+GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@
+GST_PLUGINS_ALL = @GST_PLUGINS_ALL@
+GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@
+GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@
+GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@
+GST_PLUGINS_DIR = @GST_PLUGINS_DIR@
+GST_PLUGINS_SELECTED = @GST_PLUGINS_SELECTED@
+GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@
+GST_PREFIX = @GST_PREFIX@
+GST_TOOLS_DIR = @GST_TOOLS_DIR@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_X11_CFLAGS = @GTK_X11_CFLAGS@
+GTK_X11_LIBS = @GTK_X11_LIBS@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+HAVE_AVC1394 = @HAVE_AVC1394@
+HAVE_BZ2 = @HAVE_BZ2@
+HAVE_CXX = @HAVE_CXX@
+HAVE_DIRECTSOUND = @HAVE_DIRECTSOUND@
+HAVE_GCONFTOOL = @HAVE_GCONFTOOL@
+HAVE_ROM1394 = @HAVE_ROM1394@
+HAVE_SPEEX = @HAVE_SPEEX@
+HAVE_X = @HAVE_X@
+HAVE_XSHM = @HAVE_XSHM@
+HAVE_ZLIB = @HAVE_ZLIB@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JACK_0_120_1_CFLAGS = @JACK_0_120_1_CFLAGS@
+JACK_0_120_1_LIBS = @JACK_0_120_1_LIBS@
+JACK_1_9_7_CFLAGS = @JACK_1_9_7_CFLAGS@
+JACK_1_9_7_LIBS = @JACK_1_9_7_LIBS@
+JACK_CFLAGS = @JACK_CFLAGS@
+JACK_LIBS = @JACK_LIBS@
+JPEG_LIBS = @JPEG_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCACA_CFLAGS = @LIBCACA_CFLAGS@
+LIBCACA_LIBS = @LIBCACA_LIBS@
+LIBDV_CFLAGS = @LIBDV_CFLAGS@
+LIBDV_LIBS = @LIBDV_LIBS@
+LIBICONV = @LIBICONV@
+LIBIEC61883_CFLAGS = @LIBIEC61883_CFLAGS@
+LIBIEC61883_LIBS = @LIBIEC61883_LIBS@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBPNG_CFLAGS = @LIBPNG_CFLAGS@
+LIBPNG_LIBS = @LIBPNG_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBV4L2_CFLAGS = @LIBV4L2_CFLAGS@
+LIBV4L2_LIBS = @LIBV4L2_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCALEDIR = @LOCALEDIR@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJC_LDFLAGS = @OBJC_LDFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORCC = @ORCC@
+ORCC_FLAGS = @ORCC_FLAGS@
+ORC_CFLAGS = @ORC_CFLAGS@
+ORC_LIBS = @ORC_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@
+PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PLUGINDIR = @PLUGINDIR@
+POSUB = @POSUB@
+PROFILE_CFLAGS = @PROFILE_CFLAGS@
+PULSE_0_9_20_CFLAGS = @PULSE_0_9_20_CFLAGS@
+PULSE_0_9_20_LIBS = @PULSE_0_9_20_LIBS@
+PULSE_1_0_CFLAGS = @PULSE_1_0_CFLAGS@
+PULSE_1_0_LIBS = @PULSE_1_0_LIBS@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RAW1394_CFLAGS = @RAW1394_CFLAGS@
+RAW1394_LIBS = @RAW1394_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHOUT2_CFLAGS = @SHOUT2_CFLAGS@
+SHOUT2_LIBS = @SHOUT2_LIBS@
+SOUP_CFLAGS = @SOUP_CFLAGS@
+SOUP_LIBS = @SOUP_LIBS@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+TAGLIB_CFLAGS = @TAGLIB_CFLAGS@
+TAGLIB_CXXFLAGS = @TAGLIB_CXXFLAGS@
+TAGLIB_LIBS = @TAGLIB_LIBS@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VALGRIND_PATH = @VALGRIND_PATH@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
+WAVPACK_LIBS = @WAVPACK_LIBS@
+WIN32_LIBS = @WIN32_LIBS@
+XDAMAGE_CFLAGS = @XDAMAGE_CFLAGS@
+XDAMAGE_LIBS = @XDAMAGE_LIBS@
+XFIXES_CFLAGS = @XFIXES_CFLAGS@
+XFIXES_LIBS = @XFIXES_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+XMKMF = @XMKMF@
+XSHM_LIBS = @XSHM_LIBS@
+XVIDEO_LIBS = @XVIDEO_LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = libgstossaudio.la
+libgstossaudio_la_SOURCES = gstossaudio.c \
+ gstosshelper.c \
+ gstossmixer.c \
+ gstossmixerelement.c \
+ gstossmixertrack.c \
+ gstosssink.c \
+ gstosssrc.c
+
+libgstossaudio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
+libgstossaudio_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstinterfaces-$(GST_MAJORMINOR) \
+ -lgstaudio-$(GST_MAJORMINOR) \
+ $(GST_BASE_LIBS) \
+ $(GST_LIBS)
+
+libgstossaudio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstossaudio_la_LIBTOOLFLAGS = --tag=disable-static
+noinst_HEADERS = common.h \
+ gstosssink.h \
+ gstosssrc.h \
+ gstosshelper.h \
+ gstossdmabuffer.h \
+ gstossmixer.h \
+ gstossmixerelement.h \
+ gstossmixertrack.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sys/oss/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu sys/oss/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgstossaudio.la: $(libgstossaudio_la_OBJECTS) $(libgstossaudio_la_DEPENDENCIES) $(EXTRA_libgstossaudio_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgstossaudio_la_LINK) -rpath $(plugindir) $(libgstossaudio_la_OBJECTS) $(libgstossaudio_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstossaudio_la-gstossaudio.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstossaudio_la-gstosshelper.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstossaudio_la-gstossmixer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstossaudio_la-gstossmixerelement.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstossaudio_la-gstossmixertrack.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstossaudio_la-gstosssink.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstossaudio_la-gstosssrc.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libgstossaudio_la-gstossaudio.lo: gstossaudio.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -MT libgstossaudio_la-gstossaudio.lo -MD -MP -MF $(DEPDIR)/libgstossaudio_la-gstossaudio.Tpo -c -o libgstossaudio_la-gstossaudio.lo `test -f 'gstossaudio.c' || echo '$(srcdir)/'`gstossaudio.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstossaudio_la-gstossaudio.Tpo $(DEPDIR)/libgstossaudio_la-gstossaudio.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstossaudio.c' object='libgstossaudio_la-gstossaudio.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -c -o libgstossaudio_la-gstossaudio.lo `test -f 'gstossaudio.c' || echo '$(srcdir)/'`gstossaudio.c
+
+libgstossaudio_la-gstosshelper.lo: gstosshelper.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -MT libgstossaudio_la-gstosshelper.lo -MD -MP -MF $(DEPDIR)/libgstossaudio_la-gstosshelper.Tpo -c -o libgstossaudio_la-gstosshelper.lo `test -f 'gstosshelper.c' || echo '$(srcdir)/'`gstosshelper.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstossaudio_la-gstosshelper.Tpo $(DEPDIR)/libgstossaudio_la-gstosshelper.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstosshelper.c' object='libgstossaudio_la-gstosshelper.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -c -o libgstossaudio_la-gstosshelper.lo `test -f 'gstosshelper.c' || echo '$(srcdir)/'`gstosshelper.c
+
+libgstossaudio_la-gstossmixer.lo: gstossmixer.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -MT libgstossaudio_la-gstossmixer.lo -MD -MP -MF $(DEPDIR)/libgstossaudio_la-gstossmixer.Tpo -c -o libgstossaudio_la-gstossmixer.lo `test -f 'gstossmixer.c' || echo '$(srcdir)/'`gstossmixer.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstossaudio_la-gstossmixer.Tpo $(DEPDIR)/libgstossaudio_la-gstossmixer.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstossmixer.c' object='libgstossaudio_la-gstossmixer.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -c -o libgstossaudio_la-gstossmixer.lo `test -f 'gstossmixer.c' || echo '$(srcdir)/'`gstossmixer.c
+
+libgstossaudio_la-gstossmixerelement.lo: gstossmixerelement.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -MT libgstossaudio_la-gstossmixerelement.lo -MD -MP -MF $(DEPDIR)/libgstossaudio_la-gstossmixerelement.Tpo -c -o libgstossaudio_la-gstossmixerelement.lo `test -f 'gstossmixerelement.c' || echo '$(srcdir)/'`gstossmixerelement.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstossaudio_la-gstossmixerelement.Tpo $(DEPDIR)/libgstossaudio_la-gstossmixerelement.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstossmixerelement.c' object='libgstossaudio_la-gstossmixerelement.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -c -o libgstossaudio_la-gstossmixerelement.lo `test -f 'gstossmixerelement.c' || echo '$(srcdir)/'`gstossmixerelement.c
+
+libgstossaudio_la-gstossmixertrack.lo: gstossmixertrack.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -MT libgstossaudio_la-gstossmixertrack.lo -MD -MP -MF $(DEPDIR)/libgstossaudio_la-gstossmixertrack.Tpo -c -o libgstossaudio_la-gstossmixertrack.lo `test -f 'gstossmixertrack.c' || echo '$(srcdir)/'`gstossmixertrack.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstossaudio_la-gstossmixertrack.Tpo $(DEPDIR)/libgstossaudio_la-gstossmixertrack.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstossmixertrack.c' object='libgstossaudio_la-gstossmixertrack.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -c -o libgstossaudio_la-gstossmixertrack.lo `test -f 'gstossmixertrack.c' || echo '$(srcdir)/'`gstossmixertrack.c
+
+libgstossaudio_la-gstosssink.lo: gstosssink.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -MT libgstossaudio_la-gstosssink.lo -MD -MP -MF $(DEPDIR)/libgstossaudio_la-gstosssink.Tpo -c -o libgstossaudio_la-gstosssink.lo `test -f 'gstosssink.c' || echo '$(srcdir)/'`gstosssink.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstossaudio_la-gstosssink.Tpo $(DEPDIR)/libgstossaudio_la-gstosssink.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstosssink.c' object='libgstossaudio_la-gstosssink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -c -o libgstossaudio_la-gstosssink.lo `test -f 'gstosssink.c' || echo '$(srcdir)/'`gstosssink.c
+
+libgstossaudio_la-gstosssrc.lo: gstosssrc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -MT libgstossaudio_la-gstosssrc.lo -MD -MP -MF $(DEPDIR)/libgstossaudio_la-gstosssrc.Tpo -c -o libgstossaudio_la-gstosssrc.lo `test -f 'gstosssrc.c' || echo '$(srcdir)/'`gstosssrc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstossaudio_la-gstosssrc.Tpo $(DEPDIR)/libgstossaudio_la-gstosssrc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstosssrc.c' object='libgstossaudio_la-gstosssrc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstossaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstossaudio_la_CFLAGS) $(CFLAGS) -c -o libgstossaudio_la-gstosssrc.lo `test -f 'gstosssrc.c' || echo '$(srcdir)/'`gstosssrc.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sys/oss/common.h b/sys/oss/common.h
new file mode 100644
index 0000000..2445c3d
--- /dev/null
+++ b/sys/oss/common.h
@@ -0,0 +1,43 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000,2005 Wim Taymans <wim@fluendo.com>
+ *
+ * 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.
+ */
+
+#define SET_PARAM(_oss, _name, _val, _detail) \
+G_STMT_START { \
+ int _tmp = _val; \
+ if (ioctl(_oss->fd, _name, &_tmp) == -1) { \
+ GST_ELEMENT_ERROR (_oss, RESOURCE, SETTINGS,\
+ (NULL), \
+ ("Unable to set param " _detail ": %s", \
+ g_strerror (errno))); \
+ return FALSE; \
+ } \
+ GST_DEBUG_OBJECT(_oss, _detail " %d", _tmp); \
+} G_STMT_END
+
+#define GET_PARAM(_oss, _name, _val, _detail) \
+G_STMT_START { \
+ if (ioctl(oss->fd, _name, _val) == -1) { \
+ GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, \
+ (NULL), \
+ ("Unable to get param " _detail ": %s", \
+ g_strerror (errno))); \
+ return FALSE; \
+ } \
+} G_STMT_END
diff --git a/sys/oss/gstossaudio.c b/sys/oss/gstossaudio.c
new file mode 100644
index 0000000..2a181e8
--- /dev/null
+++ b/sys/oss/gstossaudio.c
@@ -0,0 +1,61 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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 "gst/gst-i18n-plugin.h"
+
+#include "gstossmixerelement.h"
+#include "gstosssink.h"
+#include "gstosssrc.h"
+
+GST_DEBUG_CATEGORY (oss_debug);
+#define GST_CAT_DEFAULT oss_debug
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ if (!gst_element_register (plugin, "ossmixer", GST_RANK_NONE,
+ GST_TYPE_OSS_MIXER_ELEMENT) ||
+ !gst_element_register (plugin, "osssrc", GST_RANK_SECONDARY,
+ GST_TYPE_OSS_SRC) ||
+ !gst_element_register (plugin, "osssink", GST_RANK_SECONDARY,
+ GST_TYPE_OSSSINK)) {
+ return FALSE;
+ }
+
+ GST_DEBUG_CATEGORY_INIT (oss_debug, "oss", 0, "OSS elements");
+
+#ifdef ENABLE_NLS
+ GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
+ LOCALEDIR);
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+#endif /* ENABLE_NLS */
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "ossaudio",
+ "OSS (Open Sound System) support for GStreamer",
+ plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/oss/gstossdmabuffer.h b/sys/oss/gstossdmabuffer.h
new file mode 100644
index 0000000..c38ef6f
--- /dev/null
+++ b/sys/oss/gstossdmabuffer.h
@@ -0,0 +1,77 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstossdmabuffer.h:
+ *
+ * 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.
+ */
+
+#ifndef __GST_OSSDMABUFFER_H__
+#define __GST_OSSDMABUFFER_H__
+
+#include <gst/gst.h>
+
+#include "gstosshelper.h"
+#include <gst/audio/gstringbuffer.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSSDMABUFFER (gst_ossdmabuffer_get_type())
+#define GST_OSSDMABUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSSDMABUFFER,GstOssDMABuffer))
+#define GST_OSSDMABUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSSDMABUFFER,GstOssDMABufferClass))
+#define GST_IS_OSSDMABUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSSDMABUFFER))
+#define GST_IS_OSSDMABUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSSDMABUFFER))
+
+#define GST_OSSELEMENT_GET(obj) GST_OSSELEMENT (obj->element)
+
+typedef enum {
+ GST_OSSDMABUFFER_OPEN = (1 << 0),
+} GstOssDMABufferFlags;
+
+typedef struct _GstOssDMABuffer GstOssDMABuffer;
+typedef struct _GstOssDMABufferClass GstOssDMABufferClass;
+
+#define GST_OSSDMABUFFER_THREAD(buf) (GST_OSSDMABUFFER(buf)->thread)
+#define GST_OSSDMABUFFER_LOCK GST_OBJECT_LOCK
+#define GST_OSSDMABUFFER_UNLOCK GST_OBJECT_UNLOCK
+#define GST_OSSDMABUFFER_COND(buf) (GST_OSSDMABUFFER(buf)->cond)
+#define GST_OSSDMABUFFER_SIGNAL(buf) (g_cond_signal (GST_OSSDMABUFFER_COND (buf)))
+#define GST_OSSDMABUFFER_WAIT(buf) (g_cond_wait (GST_OSSDMABUFFER_COND (buf), GST_OBJECT_GET_LOCK (buf)))
+
+struct _GstOssDMABuffer {
+ GstRingBuffer buffer;
+
+ GstOssElement *element;
+
+ int fd;
+ int caps;
+ int frag;
+
+ GThread *thread;
+ GCond *cond;
+ gboolean running;
+};
+
+struct _GstOssDMABufferClass {
+ GstRingBufferClass parent_class;
+};
+
+GType gst_ossdmabuffer_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_OSSDMABUFFER_H__ */
diff --git a/sys/oss/gstosshelper.c b/sys/oss/gstosshelper.c
new file mode 100644
index 0000000..6d7e6bd
--- /dev/null
+++ b/sys/oss/gstosshelper.c
@@ -0,0 +1,407 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wim.taymans@chello.be>
+ *
+ * gstosshelper.c: OSS helper routines
+ *
+ * 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 "gst/gst-i18n-plugin.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#ifdef HAVE_OSS_INCLUDE_IN_SYS
+# include <sys/soundcard.h>
+#else
+# ifdef HAVE_OSS_INCLUDE_IN_ROOT
+# include <soundcard.h>
+# else
+# ifdef HAVE_OSS_INCLUDE_IN_MACHINE
+# include <machine/soundcard.h>
+# else
+# error "What to include?"
+# endif /* HAVE_OSS_INCLUDE_IN_MACHINE */
+# endif /* HAVE_OSS_INCLUDE_IN_ROOT */
+#endif /* HAVE_OSS_INCLUDE_IN_SYS */
+
+#include <gst/interfaces/propertyprobe.h>
+
+#include "gstosshelper.h"
+#include "gstossmixer.h"
+
+GST_DEBUG_CATEGORY_EXTERN (oss_debug);
+#define GST_CAT_DEFAULT oss_debug
+
+typedef struct _GstOssProbe GstOssProbe;
+struct _GstOssProbe
+{
+ int fd;
+ int format;
+ int n_channels;
+ GArray *rates;
+ int min;
+ int max;
+};
+
+typedef struct _GstOssRange GstOssRange;
+struct _GstOssRange
+{
+ int min;
+ int max;
+};
+
+static GstStructure *gst_oss_helper_get_format_structure (unsigned int
+ format_bit);
+static gboolean gst_oss_helper_rate_probe_check (GstOssProbe * probe);
+static int gst_oss_helper_rate_check_rate (GstOssProbe * probe, int irate);
+static void gst_oss_helper_rate_add_range (GQueue * queue, int min, int max);
+static void gst_oss_helper_rate_add_rate (GArray * array, int rate);
+static int gst_oss_helper_rate_int_compare (gconstpointer a, gconstpointer b);
+
+GstCaps *
+gst_oss_helper_probe_caps (gint fd)
+{
+ GstOssProbe *probe;
+ int i;
+ gboolean ret;
+ GstStructure *structure;
+ unsigned int format_bit;
+ unsigned int format_mask;
+ GstCaps *caps;
+
+ /* FIXME test make sure we're not currently playing */
+ /* FIXME test both mono and stereo */
+
+ format_mask = AFMT_U8 | AFMT_S8;
+
+ if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
+ format_mask |= AFMT_S16_LE | AFMT_U16_LE;
+ else
+ format_mask |= AFMT_S16_BE | AFMT_U16_BE;
+
+ caps = gst_caps_new_empty ();
+
+ /* assume that the most significant bit of format_mask is 0 */
+ for (format_bit = 1 << 31; format_bit > 0; format_bit >>= 1) {
+ if (format_bit & format_mask) {
+ GValue rate_value = { 0 };
+
+ probe = g_new0 (GstOssProbe, 1);
+ probe->fd = fd;
+ probe->format = format_bit;
+ /* FIXME: this is not working for all cards, see bug #518474 */
+ probe->n_channels = 2;
+
+ ret = gst_oss_helper_rate_probe_check (probe);
+ if (probe->min == -1 || probe->max == -1) {
+ g_array_free (probe->rates, TRUE);
+ g_free (probe);
+ continue;
+ }
+
+ if (ret) {
+ GValue value = { 0 };
+
+ g_array_sort (probe->rates, gst_oss_helper_rate_int_compare);
+
+ g_value_init (&rate_value, GST_TYPE_LIST);
+ g_value_init (&value, G_TYPE_INT);
+
+ for (i = 0; i < probe->rates->len; i++) {
+ g_value_set_int (&value, g_array_index (probe->rates, int, i));
+
+ gst_value_list_append_value (&rate_value, &value);
+ }
+
+ g_value_unset (&value);
+ } else {
+ /* one big range */
+ g_value_init (&rate_value, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&rate_value, probe->min, probe->max);
+ }
+
+ g_array_free (probe->rates, TRUE);
+ g_free (probe);
+
+ structure = gst_oss_helper_get_format_structure (format_bit);
+ gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
+ gst_structure_set_value (structure, "rate", &rate_value);
+ g_value_unset (&rate_value);
+
+ gst_caps_append_structure (caps, structure);
+ }
+ }
+
+ if (gst_caps_is_empty (caps)) {
+ /* fixme: make user-visible */
+ GST_WARNING ("Your OSS device could not be probed correctly");
+ }
+
+ GST_DEBUG ("probed caps: %" GST_PTR_FORMAT, caps);
+
+ return caps;
+}
+
+static GstStructure *
+gst_oss_helper_get_format_structure (unsigned int format_bit)
+{
+ GstStructure *structure;
+ int endianness;
+ gboolean sign;
+ int width;
+
+ switch (format_bit) {
+ case AFMT_U8:
+ endianness = 0;
+ sign = FALSE;
+ width = 8;
+ break;
+ case AFMT_S16_LE:
+ endianness = G_LITTLE_ENDIAN;
+ sign = TRUE;
+ width = 16;
+ break;
+ case AFMT_S16_BE:
+ endianness = G_BIG_ENDIAN;
+ sign = TRUE;
+ width = 16;
+ break;
+ case AFMT_S8:
+ endianness = 0;
+ sign = TRUE;
+ width = 8;
+ break;
+ case AFMT_U16_LE:
+ endianness = G_LITTLE_ENDIAN;
+ sign = FALSE;
+ width = 16;
+ break;
+ case AFMT_U16_BE:
+ endianness = G_BIG_ENDIAN;
+ sign = FALSE;
+ width = 16;
+ break;
+ default:
+ g_assert_not_reached ();
+ return NULL;
+ }
+
+ structure = gst_structure_new ("audio/x-raw-int",
+ "width", G_TYPE_INT, width,
+ "depth", G_TYPE_INT, width, "signed", G_TYPE_BOOLEAN, sign, NULL);
+
+ if (endianness) {
+ gst_structure_set (structure, "endianness", G_TYPE_INT, endianness, NULL);
+ }
+
+ return structure;
+}
+
+static gboolean
+gst_oss_helper_rate_probe_check (GstOssProbe * probe)
+{
+ GstOssRange *range;
+ GQueue *ranges;
+ int exact_rates = 0;
+ gboolean checking_exact_rates = TRUE;
+ int n_checks = 0;
+ gboolean result = TRUE;
+
+ ranges = g_queue_new ();
+
+ probe->rates = g_array_new (FALSE, FALSE, sizeof (int));
+
+ probe->min = gst_oss_helper_rate_check_rate (probe, 1000);
+ n_checks++;
+ probe->max = gst_oss_helper_rate_check_rate (probe, 100000);
+ /* a little bug workaround */
+ {
+ int max;
+
+ max = gst_oss_helper_rate_check_rate (probe, 48000);
+ if (max > probe->max) {
+ GST_ERROR
+ ("Driver bug recognized (driver does not round rates correctly). Please file a bug report.");
+ probe->max = max;
+ }
+ }
+ n_checks++;
+ if (probe->min == -1 || probe->max == -1) {
+ /* This is a workaround for drivers that return -EINVAL (or another
+ * error) for rates outside of [8000,48000]. If this fails, the
+ * driver is seriously buggy, and probably doesn't work with other
+ * media libraries/apps. */
+ probe->min = gst_oss_helper_rate_check_rate (probe, 8000);
+ probe->max = gst_oss_helper_rate_check_rate (probe, 48000);
+ }
+ if (probe->min == -1 || probe->max == -1) {
+ GST_DEBUG ("unexpected check_rate error");
+ return FALSE;
+ }
+ gst_oss_helper_rate_add_range (ranges, probe->min + 1, probe->max - 1);
+
+ while ((range = g_queue_pop_head (ranges))) {
+ int min1;
+ int max1;
+ int mid;
+ int mid_ret;
+
+ GST_DEBUG ("checking [%d,%d]", range->min, range->max);
+
+ mid = (range->min + range->max) / 2;
+ mid_ret = gst_oss_helper_rate_check_rate (probe, mid);
+ if (mid_ret == -1) {
+ /* FIXME ioctl returned an error. do something */
+ GST_DEBUG ("unexpected check_rate error");
+ }
+ n_checks++;
+
+ if (mid == mid_ret && checking_exact_rates) {
+ int max_exact_matches = 20;
+
+ exact_rates++;
+ if (exact_rates > max_exact_matches) {
+ GST_DEBUG ("got %d exact rates, assuming all are exact",
+ max_exact_matches);
+ result = FALSE;
+ g_free (range);
+ break;
+ }
+ } else {
+ checking_exact_rates = FALSE;
+ }
+
+ /* Assume that the rate is arithmetically rounded to the nearest
+ * supported rate. */
+ if (mid == mid_ret) {
+ min1 = mid - 1;
+ max1 = mid + 1;
+ } else {
+ if (mid < mid_ret) {
+ min1 = mid - (mid_ret - mid);
+ max1 = mid_ret + 1;
+ } else {
+ min1 = mid_ret - 1;
+ max1 = mid + (mid - mid_ret);
+ }
+ }
+
+ gst_oss_helper_rate_add_range (ranges, range->min, min1);
+ gst_oss_helper_rate_add_range (ranges, max1, range->max);
+
+ g_free (range);
+ }
+
+ while ((range = g_queue_pop_head (ranges))) {
+ g_free (range);
+ }
+ g_queue_free (ranges);
+
+ return result;
+}
+
+static void
+gst_oss_helper_rate_add_range (GQueue * queue, int min, int max)
+{
+ if (min <= max) {
+ GstOssRange *range = g_new0 (GstOssRange, 1);
+
+ range->min = min;
+ range->max = max;
+
+ g_queue_push_tail (queue, range);
+ /* push_head also works, but has different probing behavior */
+ /*g_queue_push_head (queue, range); */
+ }
+}
+
+static int
+gst_oss_helper_rate_check_rate (GstOssProbe * probe, int irate)
+{
+ int rate;
+ int format;
+ int n_channels;
+ int ret;
+
+ rate = irate;
+ format = probe->format;
+ n_channels = probe->n_channels;
+
+ GST_LOG ("checking format %d, channels %d, rate %d",
+ format, n_channels, rate);
+ ret = ioctl (probe->fd, SNDCTL_DSP_SETFMT, &format);
+ if (ret < 0 || format != probe->format) {
+ GST_DEBUG ("unsupported format: %d (%d)", probe->format, format);
+ return -1;
+ }
+ ret = ioctl (probe->fd, SNDCTL_DSP_CHANNELS, &n_channels);
+ if (ret < 0 || n_channels != probe->n_channels) {
+ GST_DEBUG ("unsupported channels: %d (%d)", probe->n_channels, n_channels);
+ return -1;
+ }
+ ret = ioctl (probe->fd, SNDCTL_DSP_SPEED, &rate);
+ if (ret < 0) {
+ GST_DEBUG ("unsupported rate: %d (%d)", irate, rate);
+ return -1;
+ }
+
+ GST_DEBUG ("rate %d -> %d", irate, rate);
+
+ if (rate == irate - 1 || rate == irate + 1) {
+ rate = irate;
+ }
+ gst_oss_helper_rate_add_rate (probe->rates, rate);
+ return rate;
+}
+
+static void
+gst_oss_helper_rate_add_rate (GArray * array, int rate)
+{
+ int i;
+ int val;
+
+ for (i = 0; i < array->len; i++) {
+ val = g_array_index (array, int, i);
+
+ if (val == rate)
+ return;
+ }
+ GST_DEBUG ("supported rate: %d", rate);
+ g_array_append_val (array, rate);
+}
+
+static int
+gst_oss_helper_rate_int_compare (gconstpointer a, gconstpointer b)
+{
+ const int *va = (const int *) a;
+ const int *vb = (const int *) b;
+
+ if (*va < *vb)
+ return -1;
+ if (*va > *vb)
+ return 1;
+ return 0;
+}
diff --git a/sys/oss/gstosshelper.h b/sys/oss/gstosshelper.h
new file mode 100644
index 0000000..1593fe3
--- /dev/null
+++ b/sys/oss/gstosshelper.h
@@ -0,0 +1,43 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wim.taymans@chello.be>
+ *
+ * gstosshelper.h: OSS helper routines.
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_OSS_HELPER_H__
+#define __GST_OSS_HELPER_H__
+
+
+#include <gst/gst.h>
+#include <sys/types.h>
+
+#include "gstosshelper.h"
+
+
+G_BEGIN_DECLS
+
+
+GstCaps* gst_oss_helper_probe_caps (gint fd);
+
+
+G_END_DECLS
+
+
+#endif /* __GST_OSS_HELPER_H__ */
diff --git a/sys/oss/gstossmixer.c b/sys/oss/gstossmixer.c
new file mode 100644
index 0000000..e563031
--- /dev/null
+++ b/sys/oss/gstossmixer.c
@@ -0,0 +1,378 @@
+/* GStreamer OSS Mixer implementation
+ * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * gstossmixer.c: mixer interface implementation for OSS
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#ifdef HAVE_OSS_INCLUDE_IN_SYS
+# include <sys/soundcard.h>
+#else
+# ifdef HAVE_OSS_INCLUDE_IN_ROOT
+# include <soundcard.h>
+# else
+# ifdef HAVE_OSS_INCLUDE_IN_MACHINE
+# include <machine/soundcard.h>
+# else
+# error "What to include?"
+# endif /* HAVE_OSS_INCLUDE_IN_MACHINE */
+# endif /* HAVE_OSS_INCLUDE_IN_ROOT */
+#endif /* HAVE_OSS_INCLUDE_IN_SYS */
+
+#include <gst/gst-i18n-plugin.h>
+
+#include "gstossmixer.h"
+#include "gstossmixertrack.h"
+
+GST_DEBUG_CATEGORY_EXTERN (oss_debug);
+#define GST_CAT_DEFAULT oss_debug
+
+#define MASK_BIT_IS_SET(mask, bit) \
+ (mask & (1 << bit))
+
+static gboolean
+gst_ossmixer_open (GstOssMixer * mixer)
+{
+#ifdef SOUND_MIXER_INFO
+ struct mixer_info minfo;
+#endif
+
+ g_return_val_if_fail (mixer->mixer_fd == -1, FALSE);
+
+ mixer->mixer_fd = open (mixer->device, O_RDWR);
+ if (mixer->mixer_fd == -1)
+ goto open_failed;
+
+ /* get masks */
+ if (ioctl (mixer->mixer_fd, SOUND_MIXER_READ_RECMASK, &mixer->recmask) < 0
+ || ioctl (mixer->mixer_fd, SOUND_MIXER_READ_RECSRC, &mixer->recdevs) < 0
+ || ioctl (mixer->mixer_fd, SOUND_MIXER_READ_STEREODEVS,
+ &mixer->stereomask) < 0
+ || ioctl (mixer->mixer_fd, SOUND_MIXER_READ_DEVMASK, &mixer->devmask) < 0
+ || ioctl (mixer->mixer_fd, SOUND_MIXER_READ_CAPS, &mixer->mixcaps) < 0)
+ goto masks_failed;
+
+ /* get name, not fatal */
+ g_free (mixer->cardname);
+#ifdef SOUND_MIXER_INFO
+ if (ioctl (mixer->mixer_fd, SOUND_MIXER_INFO, &minfo) == 0) {
+ mixer->cardname = g_strdup (minfo.name);
+ GST_INFO ("Card name = %s", GST_STR_NULL (mixer->cardname));
+ } else
+#endif
+ {
+ mixer->cardname = g_strdup ("Unknown");
+ GST_INFO ("Unknown card name");
+ }
+ GST_INFO ("Opened mixer for device %s", mixer->device);
+
+ return TRUE;
+
+ /* ERRORS */
+open_failed:
+ {
+ /* this is valid. OSS devices don't need to expose a mixer */
+ GST_DEBUG ("Failed to open mixer device %s, mixing disabled: %s",
+ mixer->device, strerror (errno));
+ return FALSE;
+ }
+masks_failed:
+ {
+ GST_DEBUG ("Failed to get device masks");
+ close (mixer->mixer_fd);
+ mixer->mixer_fd = -1;
+ return FALSE;
+ }
+}
+
+static void
+gst_ossmixer_ensure_track_list (GstOssMixer * mixer)
+{
+ gint i, master = -1;
+
+ g_return_if_fail (mixer->mixer_fd != -1);
+
+ if (mixer->tracklist)
+ return;
+
+ /* find master volume */
+ if (mixer->devmask & SOUND_MASK_VOLUME)
+ master = SOUND_MIXER_VOLUME;
+ else if (mixer->devmask & SOUND_MASK_PCM)
+ master = SOUND_MIXER_PCM;
+ else if (mixer->devmask & SOUND_MASK_SPEAKER)
+ master = SOUND_MIXER_SPEAKER; /* doubtful... */
+ /* else: no master, so we won't set any */
+
+ /* build track list */
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (mixer->devmask & (1 << i)) {
+ GstMixerTrack *track;
+ gboolean input = FALSE, stereo = FALSE, record = FALSE;
+
+ /* track exists, make up capabilities */
+ if (MASK_BIT_IS_SET (mixer->stereomask, i))
+ stereo = TRUE;
+ if (MASK_BIT_IS_SET (mixer->recmask, i))
+ input = TRUE;
+ if (MASK_BIT_IS_SET (mixer->recdevs, i))
+ record = TRUE;
+
+ /* do we want this in our list? */
+ if (!((mixer->dir & GST_OSS_MIXER_CAPTURE && input == TRUE) ||
+ (mixer->dir & GST_OSS_MIXER_PLAYBACK && i != SOUND_MIXER_PCM)))
+ /* the PLAYBACK case seems hacky, but that's how 0.8 had it */
+ continue;
+
+ /* add track to list */
+ track = gst_ossmixer_track_new (mixer->mixer_fd, i, stereo ? 2 : 1,
+ (record ? GST_MIXER_TRACK_RECORD : 0) |
+ (input ? GST_MIXER_TRACK_INPUT :
+ GST_MIXER_TRACK_OUTPUT) |
+ ((master != i) ? 0 : GST_MIXER_TRACK_MASTER));
+ mixer->tracklist = g_list_append (mixer->tracklist, track);
+ }
+ }
+}
+
+GstOssMixer *
+gst_ossmixer_new (const char *device, GstOssMixerDirection dir)
+{
+ GstOssMixer *ret = NULL;
+
+ g_return_val_if_fail (device != NULL, NULL);
+
+ ret = g_new0 (GstOssMixer, 1);
+
+ ret->device = g_strdup (device);
+ ret->dir = dir;
+ ret->mixer_fd = -1;
+
+ if (!gst_ossmixer_open (ret))
+ goto error;
+
+ return ret;
+
+ /* ERRORS */
+error:
+ {
+ gst_ossmixer_free (ret);
+ return NULL;
+ }
+}
+
+void
+gst_ossmixer_free (GstOssMixer * mixer)
+{
+ g_return_if_fail (mixer != NULL);
+
+ if (mixer->device) {
+ g_free (mixer->device);
+ mixer->device = NULL;
+ }
+
+ if (mixer->cardname) {
+ g_free (mixer->cardname);
+ mixer->cardname = NULL;
+ }
+
+ if (mixer->tracklist) {
+ g_list_foreach (mixer->tracklist, (GFunc) g_object_unref, NULL);
+ g_list_free (mixer->tracklist);
+ mixer->tracklist = NULL;
+ }
+
+ if (mixer->mixer_fd != -1) {
+ close (mixer->mixer_fd);
+ mixer->mixer_fd = -1;
+ }
+
+ g_free (mixer);
+}
+
+/* unused with G_DISABLE_* */
+static G_GNUC_UNUSED gboolean
+gst_ossmixer_contains_track (GstOssMixer * mixer, GstOssMixerTrack * osstrack)
+{
+ const GList *item;
+
+ for (item = mixer->tracklist; item != NULL; item = item->next)
+ if (item->data == osstrack)
+ return TRUE;
+
+ return FALSE;
+}
+
+const GList *
+gst_ossmixer_list_tracks (GstOssMixer * mixer)
+{
+ gst_ossmixer_ensure_track_list (mixer);
+
+ return (const GList *) mixer->tracklist;
+}
+
+void
+gst_ossmixer_get_volume (GstOssMixer * mixer,
+ GstMixerTrack * track, gint * volumes)
+{
+ gint volume;
+ GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
+
+ g_return_if_fail (mixer->mixer_fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
+
+ if (track->flags & GST_MIXER_TRACK_MUTE) {
+ volumes[0] = osstrack->lvol;
+ if (track->num_channels == 2) {
+ volumes[1] = osstrack->rvol;
+ }
+ } else {
+ /* get */
+ if (ioctl (mixer->mixer_fd, MIXER_READ (osstrack->track_num), &volume) < 0) {
+ g_warning ("Error getting recording device (%d) volume: %s",
+ osstrack->track_num, strerror (errno));
+ volume = 0;
+ }
+
+ osstrack->lvol = volumes[0] = (volume & 0xff);
+ if (track->num_channels == 2) {
+ osstrack->rvol = volumes[1] = ((volume >> 8) & 0xff);
+ }
+ }
+}
+
+void
+gst_ossmixer_set_volume (GstOssMixer * mixer,
+ GstMixerTrack * track, gint * volumes)
+{
+ gint volume;
+ GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
+
+ g_return_if_fail (mixer->mixer_fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
+
+ /* prepare the value for ioctl() */
+ if (!(track->flags & GST_MIXER_TRACK_MUTE)) {
+ volume = (volumes[0] & 0xff);
+ if (track->num_channels == 2) {
+ volume |= ((volumes[1] & 0xff) << 8);
+ }
+
+ /* set */
+ if (ioctl (mixer->mixer_fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) {
+ g_warning ("Error setting recording device (%d) volume (0x%x): %s",
+ osstrack->track_num, volume, strerror (errno));
+ return;
+ }
+ }
+
+ osstrack->lvol = volumes[0];
+ if (track->num_channels == 2) {
+ osstrack->rvol = volumes[1];
+ }
+}
+
+void
+gst_ossmixer_set_mute (GstOssMixer * mixer, GstMixerTrack * track,
+ gboolean mute)
+{
+ int volume;
+ GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
+
+ g_return_if_fail (mixer->mixer_fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
+
+ if (mute) {
+ volume = 0;
+ } else {
+ volume = (osstrack->lvol & 0xff);
+ if (MASK_BIT_IS_SET (mixer->stereomask, osstrack->track_num)) {
+ volume |= ((osstrack->rvol & 0xff) << 8);
+ }
+ }
+
+ if (ioctl (mixer->mixer_fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) {
+ g_warning ("Error setting mixer recording device volume (0x%x): %s",
+ volume, strerror (errno));
+ return;
+ }
+
+ if (mute) {
+ track->flags |= GST_MIXER_TRACK_MUTE;
+ } else {
+ track->flags &= ~GST_MIXER_TRACK_MUTE;
+ }
+}
+
+void
+gst_ossmixer_set_record (GstOssMixer * mixer,
+ GstMixerTrack * track, gboolean record)
+{
+ GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
+
+ g_return_if_fail (mixer->mixer_fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
+
+ /* if there's nothing to do... */
+ if ((record && GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)) ||
+ (!record && !GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)))
+ return;
+
+ /* if we're exclusive, then we need to unset the current one(s) */
+ if (mixer->mixcaps & SOUND_CAP_EXCL_INPUT) {
+ GList *track;
+
+ for (track = mixer->tracklist; track != NULL; track = track->next) {
+ GstMixerTrack *turn = (GstMixerTrack *) track->data;
+
+ turn->flags &= ~GST_MIXER_TRACK_RECORD;
+ }
+ mixer->recdevs = 0;
+ }
+
+ /* set new record bit, if needed */
+ if (record) {
+ mixer->recdevs |= (1 << osstrack->track_num);
+ } else {
+ mixer->recdevs &= ~(1 << osstrack->track_num);
+ }
+
+ /* set it to the device */
+ if (ioctl (mixer->mixer_fd, SOUND_MIXER_WRITE_RECSRC, &mixer->recdevs) < 0) {
+ g_warning ("Error setting mixer recording devices (0x%x): %s",
+ mixer->recdevs, strerror (errno));
+ return;
+ }
+
+ if (record) {
+ track->flags |= GST_MIXER_TRACK_RECORD;
+ } else {
+ track->flags &= ~GST_MIXER_TRACK_RECORD;
+ }
+}
diff --git a/sys/oss/gstossmixer.h b/sys/oss/gstossmixer.h
new file mode 100644
index 0000000..d2e06fe
--- /dev/null
+++ b/sys/oss/gstossmixer.h
@@ -0,0 +1,171 @@
+/* GStreamer OSS Mixer implementation
+ * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * gstossmixer.h: mixer interface implementation for OSS
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_OSS_MIXER_H__
+#define __GST_OSS_MIXER_H__
+
+
+#include <gst/gst.h>
+#include <gst/interfaces/mixer.h>
+
+#include "gstosshelper.h"
+
+
+G_BEGIN_DECLS
+
+
+#define GST_OSS_MIXER(obj) ((GstOssMixer*)(obj))
+
+
+typedef enum {
+ GST_OSS_MIXER_CAPTURE = 1<<0,
+ GST_OSS_MIXER_PLAYBACK = 1<<1,
+ GST_OSS_MIXER_ALL = GST_OSS_MIXER_CAPTURE | GST_OSS_MIXER_PLAYBACK
+} GstOssMixerDirection;
+
+
+typedef struct _GstOssMixer GstOssMixer;
+
+
+struct _GstOssMixer {
+ GList * tracklist; /* list of available tracks */
+
+ gint mixer_fd;
+
+ gchar * device;
+ gchar * cardname;
+
+ gint recmask;
+ gint recdevs;
+ gint stereomask;
+ gint devmask;
+ gint mixcaps;
+
+ GstOssMixerDirection dir;
+};
+
+
+GstOssMixer* gst_ossmixer_new (const gchar *device,
+ GstOssMixerDirection dir);
+void gst_ossmixer_free (GstOssMixer *mixer);
+
+const GList* gst_ossmixer_list_tracks (GstOssMixer * mixer);
+void gst_ossmixer_set_volume (GstOssMixer * mixer,
+ GstMixerTrack * track,
+ gint * volumes);
+void gst_ossmixer_get_volume (GstOssMixer * mixer,
+ GstMixerTrack * track,
+ gint * volumes);
+void gst_ossmixer_set_record (GstOssMixer * mixer,
+ GstMixerTrack * track,
+ gboolean record);
+void gst_ossmixer_set_mute (GstOssMixer * mixer,
+ GstMixerTrack * track,
+ gboolean mute);
+
+
+#define GST_IMPLEMENT_OSS_MIXER_METHODS(Type, interface_as_function) \
+static gboolean \
+interface_as_function ## _supported (Type *this, GType iface_type) \
+{ \
+ g_assert (iface_type == GST_TYPE_MIXER); \
+ \
+ return (this->mixer != NULL); \
+} \
+ \
+static const GList* \
+interface_as_function ## _list_tracks (GstMixer * mixer) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_val_if_fail (this != NULL, NULL); \
+ g_return_val_if_fail (this->mixer != NULL, NULL); \
+ \
+ return gst_ossmixer_list_tracks (this->mixer); \
+} \
+ \
+static void \
+interface_as_function ## _set_volume (GstMixer * mixer, GstMixerTrack * track, \
+ gint * volumes) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_ossmixer_set_volume (this->mixer, track, volumes); \
+} \
+ \
+static void \
+interface_as_function ## _get_volume (GstMixer * mixer, GstMixerTrack * track, \
+ gint * volumes) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_ossmixer_get_volume (this->mixer, track, volumes); \
+} \
+ \
+static void \
+interface_as_function ## _set_record (GstMixer * mixer, GstMixerTrack * track, \
+ gboolean record) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_ossmixer_set_record (this->mixer, track, record); \
+} \
+ \
+static void \
+interface_as_function ## _set_mute (GstMixer * mixer, GstMixerTrack * track, \
+ gboolean mute) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_ossmixer_set_mute (this->mixer, track, mute); \
+} \
+ \
+static void \
+interface_as_function ## _interface_init (GstMixerClass * klass) \
+{ \
+ GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE; \
+ \
+ /* set up the interface hooks */ \
+ klass->list_tracks = interface_as_function ## _list_tracks; \
+ klass->set_volume = interface_as_function ## _set_volume; \
+ klass->get_volume = interface_as_function ## _get_volume; \
+ klass->set_mute = interface_as_function ## _set_mute; \
+ klass->set_record = interface_as_function ## _set_record; \
+}
+
+
+G_END_DECLS
+
+
+#endif /* __GST_OSS_MIXER_H__ */
diff --git a/sys/oss/gstossmixerelement.c b/sys/oss/gstossmixerelement.c
new file mode 100644
index 0000000..7ceb2b8
--- /dev/null
+++ b/sys/oss/gstossmixerelement.c
@@ -0,0 +1,218 @@
+/* OSS mixer interface element.
+ * Copyright (C) 2005 Andrew Vander Wingo <wingo@pobox.com>
+ *
+ * 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-ossmixer
+ *
+ * This element lets you adjust sound input and output levels with the
+ * Open Sound System (OSS). It supports the #GstMixer interface, which can be
+ * used to obtain a list of available mixer tracks. Set the mixer element to
+ * READY state before using the #GstMixer interface on it.
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * <para>
+ * ossmixer can't be used in a sensible way in gst-launch.
+ * </para>
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstossmixerelement.h"
+
+GST_DEBUG_CATEGORY_EXTERN (oss_debug);
+#define GST_CAT_DEFAULT oss_debug
+
+#define DEFAULT_DEVICE "/dev/mixer"
+#define DEFAULT_DEVICE_NAME NULL
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+ PROP_DEVICE_NAME
+};
+
+GST_BOILERPLATE_WITH_INTERFACE (GstOssMixerElement, gst_oss_mixer_element,
+ GstElement, GST_TYPE_ELEMENT, GstMixer, GST_TYPE_MIXER,
+ gst_oss_mixer_element);
+
+GST_IMPLEMENT_OSS_MIXER_METHODS (GstOssMixerElement, gst_oss_mixer_element);
+
+static GstStateChangeReturn gst_oss_mixer_element_change_state (GstElement *
+ element, GstStateChange transition);
+
+static void gst_oss_mixer_element_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_oss_mixer_element_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec);
+static void gst_oss_mixer_element_finalize (GObject * object);
+
+static void
+gst_oss_mixer_element_base_init (gpointer klass)
+{
+ gst_element_class_set_details_simple (GST_ELEMENT_CLASS (klass), "OSS Mixer",
+ "Generic/Audio",
+ "Control sound input and output levels with OSS",
+ "Andrew Vander Wingo <wingo@pobox.com>");
+}
+
+static void
+gst_oss_mixer_element_class_init (GstOssMixerElementClass * klass)
+{
+ GstElementClass *element_class;
+ GObjectClass *gobject_class;
+
+ element_class = (GstElementClass *) klass;
+ gobject_class = (GObjectClass *) klass;
+
+ gobject_class->finalize = gst_oss_mixer_element_finalize;
+ gobject_class->set_property = gst_oss_mixer_element_set_property;
+ gobject_class->get_property = gst_oss_mixer_element_get_property;
+
+ /**
+ * GstOssMixerElement:device
+ *
+ * OSS mixer device (usually /dev/mixer)
+ *
+ * Since: 0.10.5
+ **/
+ g_object_class_install_property (gobject_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device",
+ "OSS mixer device (usually /dev/mixer)", DEFAULT_DEVICE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
+ g_param_spec_string ("device-name", "Device name",
+ "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ element_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_oss_mixer_element_change_state);
+}
+
+static void
+gst_oss_mixer_element_finalize (GObject * obj)
+{
+ GstOssMixerElement *this = GST_OSS_MIXER_ELEMENT (obj);
+
+ g_free (this->device);
+
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+static void
+gst_oss_mixer_element_init (GstOssMixerElement * this,
+ GstOssMixerElementClass * g_class)
+{
+ this->mixer = NULL;
+ this->device = g_strdup (DEFAULT_DEVICE);
+}
+
+static void
+gst_oss_mixer_element_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOssMixerElement *this = GST_OSS_MIXER_ELEMENT (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_free (this->device);
+ this->device = g_value_dup_string (value);
+ /* make sure we never set NULL */
+ if (this->device == NULL) {
+ this->device = g_strdup (DEFAULT_DEVICE);
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_oss_mixer_element_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstOssMixerElement *this = GST_OSS_MIXER_ELEMENT (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_value_set_string (value, this->device);
+ break;
+ case PROP_DEVICE_NAME:
+ if (this->mixer) {
+ g_value_set_string (value, this->mixer->cardname);
+ } else {
+ g_value_set_string (value, NULL);
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstStateChangeReturn
+gst_oss_mixer_element_change_state (GstElement * element,
+ GstStateChange transition)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ GstOssMixerElement *this = GST_OSS_MIXER_ELEMENT (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ if (!this->mixer) {
+ this->mixer = gst_ossmixer_new (this->device, GST_OSS_MIXER_ALL);
+ if (!this->mixer)
+ goto open_failed;
+ }
+ break;
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ if (this->mixer) {
+ gst_ossmixer_free (this->mixer);
+ this->mixer = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+ return ret;
+
+ /* ERRORS */
+open_failed:
+ {
+ GST_ELEMENT_ERROR (element, RESOURCE, OPEN_READ_WRITE, (NULL),
+ ("Failed to open oss mixer device '%s'", this->device));
+ return GST_STATE_CHANGE_FAILURE;
+ }
+}
diff --git a/sys/oss/gstossmixerelement.h b/sys/oss/gstossmixerelement.h
new file mode 100644
index 0000000..2d47e0e
--- /dev/null
+++ b/sys/oss/gstossmixerelement.h
@@ -0,0 +1,59 @@
+/* OSS mixer interface element.
+ * Copyright (C) 2005 Andrew Vander Wingo <wingo@pobox.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef __GST_OSS_MIXER_ELEMENT_H__
+#define __GST_OSS_MIXER_ELEMENT_H__
+
+
+#include "gstossmixer.h"
+
+
+G_BEGIN_DECLS
+
+
+#define GST_OSS_MIXER_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS_MIXER_ELEMENT,GstOssMixerElement))
+#define GST_OSS_MIXER_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS_MIXER_ELEMENT,GstOssMixerElementClass))
+#define GST_IS_OSS_MIXER_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS_MIXER_ELEMENT))
+#define GST_IS_OSS_MIXER_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS_MIXER_ELEMENT))
+#define GST_TYPE_OSS_MIXER_ELEMENT (gst_oss_mixer_element_get_type())
+
+
+typedef struct _GstOssMixerElement GstOssMixerElement;
+typedef struct _GstOssMixerElementClass GstOssMixerElementClass;
+
+
+struct _GstOssMixerElement {
+ GstElement parent;
+
+ gchar *device;
+ GstOssMixer *mixer;
+};
+
+struct _GstOssMixerElementClass {
+ GstElementClass parent;
+};
+
+
+GType gst_oss_mixer_element_get_type (void);
+
+
+G_END_DECLS
+
+
+#endif /* __GST_OSS_MIXER_ELEMENT_H__ */
diff --git a/sys/oss/gstossmixertrack.c b/sys/oss/gstossmixertrack.c
new file mode 100644
index 0000000..3bc8cde
--- /dev/null
+++ b/sys/oss/gstossmixertrack.c
@@ -0,0 +1,172 @@
+/* GStreamer OSS Mixer implementation
+ * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * gstossmixer.c: mixer interface implementation for OSS
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#ifdef HAVE_OSS_INCLUDE_IN_SYS
+# include <sys/soundcard.h>
+#else
+# ifdef HAVE_OSS_INCLUDE_IN_ROOT
+# include <soundcard.h>
+# else
+# ifdef HAVE_OSS_INCLUDE_IN_MACHINE
+# include <machine/soundcard.h>
+# else
+# error "What to include?"
+# endif /* HAVE_OSS_INCLUDE_IN_MACHINE */
+# endif /* HAVE_OSS_INCLUDE_IN_ROOT */
+#endif /* HAVE_OSS_INCLUDE_IN_SYS */
+
+#include <gst/gst-i18n-plugin.h>
+
+#include "gstossmixertrack.h"
+
+GST_DEBUG_CATEGORY_EXTERN (oss_debug);
+#define GST_CAT_DEFAULT oss_debug
+
+#define MASK_BIT_IS_SET(mask, bit) \
+ (mask & (1 << bit))
+
+G_DEFINE_TYPE (GstOssMixerTrack, gst_ossmixer_track, GST_TYPE_MIXER_TRACK);
+
+static void
+gst_ossmixer_track_class_init (GstOssMixerTrackClass * klass)
+{
+ /* nop */
+}
+
+static void
+gst_ossmixer_track_init (GstOssMixerTrack * track)
+{
+ track->lvol = track->rvol = 0;
+ track->track_num = 0;
+}
+
+static const gchar **labels = NULL;
+
+/* three functions: firstly, OSS has the nasty habit of inserting
+ * spaces in the labels, we want to get rid of them. Secondly,
+ * i18n is impossible with OSS' way of providing us with mixer
+ * labels, so we make a 'given' list of i18n'ed labels. Thirdly, I
+ * personally don't like the "1337" names that OSS gives to their
+ * labels ("Vol", "Mic", "Rec"), I'd rather see full names. */
+
+static void
+fill_labels (void)
+{
+ gint i, pos;
+ const gchar *origs[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
+ const struct
+ {
+ const gchar *given;
+ const gchar *wanted;
+ }
+ cases[] = {
+ /* Note: this list is simply ripped from soundcard.h. For
+ * some people, some values might be missing (3D surround,
+ * etc.) - feel free to add them. That's the reason why
+ * I'm doing this in such a horribly complicated way. */
+ {
+ "Vol ", _("Volume")}, {
+ "Bass ", _("Bass")}, {
+ "Trebl", _("Treble")}, {
+ "Synth", _("Synth")}, {
+ "Pcm ", _("PCM")}, {
+ "Spkr ", _("Speaker")}, {
+ "Line ", _("Line-in")}, {
+ "Mic ", _("Microphone")}, {
+ "CD ", _("CD")}, {
+ "Mix ", _("Mixer")}, {
+ "Pcm2 ", _("PCM-2")}, {
+ "Rec ", _("Record")}, {
+ "IGain", _("In-gain")}, {
+ "OGain", _("Out-gain")}, {
+ "Line1", _("Line-1")}, {
+ "Line2", _("Line-2")}, {
+ "Line3", _("Line-3")}, {
+ "Digital1", _("Digital-1")}, {
+ "Digital2", _("Digital-2")}, {
+ "Digital3", _("Digital-3")}, {
+ "PhoneIn", _("Phone-in")}, {
+ "PhoneOut", _("Phone-out")}, {
+ "Video", _("Video")}, {
+ "Radio", _("Radio")}, {
+ "Monitor", _("Monitor")}, {
+ NULL, NULL}
+ };
+
+ labels = g_malloc (sizeof (gchar *) * SOUND_MIXER_NRDEVICES);
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ for (pos = 0; cases[pos].given != NULL; pos++) {
+ if (!strcmp (cases[pos].given, origs[i])) {
+ labels[i] = g_strdup (cases[pos].wanted);
+ break;
+ }
+ }
+ if (cases[pos].given == NULL)
+ labels[i] = g_strdup (origs[i]);
+ }
+}
+
+GstMixerTrack *
+gst_ossmixer_track_new (gint mixer_fd,
+ gint track_num, gint max_chans, gint flags)
+{
+ GstOssMixerTrack *osstrack;
+ GstMixerTrack *track;
+ gint volume;
+
+ if (!labels)
+ fill_labels ();
+
+ osstrack = g_object_new (GST_TYPE_OSSMIXER_TRACK, NULL);
+ track = GST_MIXER_TRACK (osstrack);
+ track->label = g_strdup (labels[track_num]);
+ track->num_channels = max_chans;
+ track->flags = flags;
+ track->min_volume = 0;
+ track->max_volume = 100;
+ osstrack->track_num = track_num;
+
+ /* volume */
+ if (ioctl (mixer_fd, MIXER_READ (osstrack->track_num), &volume) < 0) {
+ g_warning ("Error getting device (%d) volume: %s",
+ osstrack->track_num, strerror (errno));
+ volume = 0;
+ }
+ osstrack->lvol = (volume & 0xff);
+ if (track->num_channels == 2) {
+ osstrack->rvol = ((volume >> 8) & 0xff);
+ }
+
+ return track;
+}
diff --git a/sys/oss/gstossmixertrack.h b/sys/oss/gstossmixertrack.h
new file mode 100644
index 0000000..2e62ec8
--- /dev/null
+++ b/sys/oss/gstossmixertrack.h
@@ -0,0 +1,62 @@
+/* GStreamer OSS Mixer implementation
+ * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * gstossmixertrack.h: OSS mixer tracks
+ *
+ * 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.
+ */
+
+#ifndef __GST_OSS_MIXER_TRACK_H__
+#define __GST_OSS_MIXER_TRACK_H__
+
+#include <gst/gst.h>
+#include <gst/interfaces/mixer.h>
+
+#include "gstosshelper.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSSMIXER_TRACK \
+ (gst_ossmixer_track_get_type ())
+#define GST_OSSMIXER_TRACK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_OSSMIXER_TRACK, \
+ GstOssMixerTrack))
+#define GST_OSSMIXER_TRACK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_OSSMIXER_TRACK, \
+ GstOssMixerTrackClass))
+#define GST_IS_OSSMIXER_TRACK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OSSMIXER_TRACK))
+#define GST_IS_OSSMIXER_TRACK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_OSSMIXER_TRACK))
+
+typedef struct _GstOssMixerTrack {
+ GstMixerTrack parent;
+
+ gint lvol, rvol;
+ gint track_num;
+} GstOssMixerTrack;
+
+typedef struct _GstOssMixerTrackClass {
+ GstMixerTrackClass parent;
+} GstOssMixerTrackClass;
+
+GType gst_ossmixer_track_get_type (void);
+GstMixerTrack* gst_ossmixer_track_new (gint mixer_fd,
+ gint track_num, gint max_chans, gint flags);
+
+G_END_DECLS
+
+#endif /* __GST_OSS_MIXER_TRACK_H__ */
diff --git a/sys/oss/gstosssink.c b/sys/oss/gstosssink.c
new file mode 100644
index 0000000..a604d9c
--- /dev/null
+++ b/sys/oss/gstosssink.c
@@ -0,0 +1,565 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000,2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstosssink.c:
+ *
+ * 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-osssink
+ *
+ * This element lets you output sound using the Open Sound System (OSS).
+ *
+ * Note that you should almost always use generic audio conversion elements
+ * like audioconvert and audioresample in front of an audiosink to make sure
+ * your pipeline works under all circumstances (those conversion elements will
+ * act in passthrough-mode if no conversion is necessary).
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * |[
+ * gst-launch -v audiotestsrc ! audioconvert ! volume volume=0.1 ! osssink
+ * ]| will output a sine wave (continuous beep sound) to your sound card (with
+ * a very low volume as precaution).
+ * |[
+ * gst-launch -v filesrc location=music.ogg ! decodebin ! audioconvert ! audioresample ! osssink
+ * ]| will play an Ogg/Vorbis audio file and output it using the Open Sound System.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifdef HAVE_OSS_INCLUDE_IN_SYS
+# include <sys/soundcard.h>
+#else
+# ifdef HAVE_OSS_INCLUDE_IN_ROOT
+# include <soundcard.h>
+# else
+# ifdef HAVE_OSS_INCLUDE_IN_MACHINE
+# include <machine/soundcard.h>
+# else
+# error "What to include?"
+# endif /* HAVE_OSS_INCLUDE_IN_MACHINE */
+# endif /* HAVE_OSS_INCLUDE_IN_ROOT */
+#endif /* HAVE_OSS_INCLUDE_IN_SYS */
+
+#include "common.h"
+#include "gstosssink.h"
+
+#include <gst/gst-i18n-plugin.h>
+
+GST_DEBUG_CATEGORY_EXTERN (oss_debug);
+#define GST_CAT_DEFAULT oss_debug
+
+static void gst_oss_sink_base_init (gpointer g_class);
+static void gst_oss_sink_class_init (GstOssSinkClass * klass);
+static void gst_oss_sink_init (GstOssSink * osssink);
+
+static void gst_oss_sink_dispose (GObject * object);
+static void gst_oss_sink_finalise (GObject * object);
+
+static void gst_oss_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static void gst_oss_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+
+static GstCaps *gst_oss_sink_getcaps (GstBaseSink * bsink);
+
+static gboolean gst_oss_sink_open (GstAudioSink * asink);
+static gboolean gst_oss_sink_close (GstAudioSink * asink);
+static gboolean gst_oss_sink_prepare (GstAudioSink * asink,
+ GstRingBufferSpec * spec);
+static gboolean gst_oss_sink_unprepare (GstAudioSink * asink);
+static guint gst_oss_sink_write (GstAudioSink * asink, gpointer data,
+ guint length);
+static guint gst_oss_sink_delay (GstAudioSink * asink);
+static void gst_oss_sink_reset (GstAudioSink * asink);
+
+/* OssSink signals and args */
+enum
+{
+ LAST_SIGNAL
+};
+
+#define DEFAULT_DEVICE "/dev/dsp"
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+};
+
+static GstStaticPadTemplate osssink_sink_factory =
+ GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-int, "
+ "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, "
+ "signed = (boolean) { TRUE, FALSE }, "
+ "width = (int) 16, "
+ "depth = (int) 16, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
+ "audio/x-raw-int, "
+ "signed = (boolean) { TRUE, FALSE }, "
+ "width = (int) 8, "
+ "depth = (int) 8, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
+ );
+
+static GstElementClass *parent_class = NULL;
+
+/* static guint gst_oss_sink_signals[LAST_SIGNAL] = { 0 }; */
+
+GType
+gst_oss_sink_get_type (void)
+{
+ static GType osssink_type = 0;
+
+ if (!osssink_type) {
+ static const GTypeInfo osssink_info = {
+ sizeof (GstOssSinkClass),
+ gst_oss_sink_base_init,
+ NULL,
+ (GClassInitFunc) gst_oss_sink_class_init,
+ NULL,
+ NULL,
+ sizeof (GstOssSink),
+ 0,
+ (GInstanceInitFunc) gst_oss_sink_init,
+ };
+
+ osssink_type =
+ g_type_register_static (GST_TYPE_AUDIO_SINK, "GstOssSink",
+ &osssink_info, 0);
+ }
+
+ return osssink_type;
+}
+
+static void
+gst_oss_sink_dispose (GObject * object)
+{
+ GstOssSink *osssink = GST_OSSSINK (object);
+
+ if (osssink->probed_caps) {
+ gst_caps_unref (osssink->probed_caps);
+ osssink->probed_caps = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_oss_sink_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_set_details_simple (element_class, "Audio Sink (OSS)",
+ "Sink/Audio",
+ "Output to a sound card via OSS",
+ "Erik Walthinsen <omega@cse.ogi.edu>, "
+ "Wim Taymans <wim.taymans@chello.be>");
+
+ gst_element_class_add_static_pad_template (element_class,
+ &osssink_sink_factory);
+}
+
+static void
+gst_oss_sink_class_init (GstOssSinkClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstBaseSinkClass *gstbasesink_class;
+ GstAudioSinkClass *gstaudiosink_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstbasesink_class = (GstBaseSinkClass *) klass;
+ gstaudiosink_class = (GstAudioSinkClass *) klass;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->dispose = gst_oss_sink_dispose;
+ gobject_class->finalize = gst_oss_sink_finalise;
+ gobject_class->get_property = gst_oss_sink_get_property;
+ gobject_class->set_property = gst_oss_sink_set_property;
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device",
+ "OSS device (usually /dev/dspN)", DEFAULT_DEVICE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_oss_sink_getcaps);
+
+ gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_oss_sink_open);
+ gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_oss_sink_close);
+ gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_oss_sink_prepare);
+ gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_oss_sink_unprepare);
+ gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_oss_sink_write);
+ gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_oss_sink_delay);
+ gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_oss_sink_reset);
+}
+
+static void
+gst_oss_sink_init (GstOssSink * osssink)
+{
+ const gchar *device;
+
+ GST_DEBUG_OBJECT (osssink, "initializing osssink");
+
+ device = g_getenv ("AUDIODEV");
+ if (device == NULL)
+ device = DEFAULT_DEVICE;
+ osssink->device = g_strdup (device);
+ osssink->fd = -1;
+}
+
+static void
+gst_oss_sink_finalise (GObject * object)
+{
+ GstOssSink *osssink = GST_OSSSINK (object);
+
+ g_free (osssink->device);
+
+ G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (object));
+}
+
+static void
+gst_oss_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOssSink *sink;
+
+ sink = GST_OSSSINK (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_free (sink->device);
+ sink->device = g_value_dup_string (value);
+ if (sink->probed_caps) {
+ gst_caps_unref (sink->probed_caps);
+ sink->probed_caps = NULL;
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_oss_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstOssSink *sink;
+
+ sink = GST_OSSSINK (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_value_set_string (value, sink->device);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstCaps *
+gst_oss_sink_getcaps (GstBaseSink * bsink)
+{
+ GstOssSink *osssink;
+ GstCaps *caps;
+
+ osssink = GST_OSSSINK (bsink);
+
+ if (osssink->fd == -1) {
+ caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD
+ (bsink)));
+ } else if (osssink->probed_caps) {
+ caps = gst_caps_copy (osssink->probed_caps);
+ } else {
+ caps = gst_oss_helper_probe_caps (osssink->fd);
+ if (caps && !gst_caps_is_empty (caps)) {
+ osssink->probed_caps = gst_caps_copy (caps);
+ }
+ }
+
+ return caps;
+}
+
+static gint
+ilog2 (gint x)
+{
+ /* well... hacker's delight explains... */
+ x = x | (x >> 1);
+ x = x | (x >> 2);
+ x = x | (x >> 4);
+ x = x | (x >> 8);
+ x = x | (x >> 16);
+ x = x - ((x >> 1) & 0x55555555);
+ x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+ x = (x + (x >> 4)) & 0x0f0f0f0f;
+ x = x + (x >> 8);
+ x = x + (x >> 16);
+ return (x & 0x0000003f) - 1;
+}
+
+static gint
+gst_oss_sink_get_format (GstBufferFormat fmt)
+{
+ gint result;
+
+ switch (fmt) {
+ case GST_MU_LAW:
+ result = AFMT_MU_LAW;
+ break;
+ case GST_A_LAW:
+ result = AFMT_A_LAW;
+ break;
+ case GST_IMA_ADPCM:
+ result = AFMT_IMA_ADPCM;
+ break;
+ case GST_U8:
+ result = AFMT_U8;
+ break;
+ case GST_S16_LE:
+ result = AFMT_S16_LE;
+ break;
+ case GST_S16_BE:
+ result = AFMT_S16_BE;
+ break;
+ case GST_S8:
+ result = AFMT_S8;
+ break;
+ case GST_U16_LE:
+ result = AFMT_U16_LE;
+ break;
+ case GST_U16_BE:
+ result = AFMT_U16_BE;
+ break;
+ case GST_MPEG:
+ result = AFMT_MPEG;
+ break;
+ default:
+ result = 0;
+ break;
+ }
+ return result;
+}
+
+static gboolean
+gst_oss_sink_open (GstAudioSink * asink)
+{
+ GstOssSink *oss;
+ int mode;
+
+ oss = GST_OSSSINK (asink);
+
+ mode = O_WRONLY;
+ mode |= O_NONBLOCK;
+
+ oss->fd = open (oss->device, mode, 0);
+ if (oss->fd == -1) {
+ switch (errno) {
+ case EBUSY:
+ goto busy;
+ case EACCES:
+ goto no_permission;
+ default:
+ goto open_failed;
+ }
+ }
+
+ return TRUE;
+
+ /* ERRORS */
+busy:
+ {
+ GST_ELEMENT_ERROR (oss, RESOURCE, BUSY,
+ (_("Could not open audio device for playback. "
+ "Device is being used by another application.")), (NULL));
+ return FALSE;
+ }
+no_permission:
+ {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
+ (_("Could not open audio device for playback. "
+ "You don't have permission to open the device.")),
+ GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+open_failed:
+ {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
+ (_("Could not open audio device for playback.")), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_oss_sink_close (GstAudioSink * asink)
+{
+ close (GST_OSSSINK (asink)->fd);
+ GST_OSSSINK (asink)->fd = -1;
+ return TRUE;
+}
+
+static gboolean
+gst_oss_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
+{
+ GstOssSink *oss;
+ struct audio_buf_info info;
+ int mode;
+ int tmp;
+
+ oss = GST_OSSSINK (asink);
+
+ /* we opened non-blocking so that we can detect if the device is available
+ * without hanging forever. We now want to remove the non-blocking flag. */
+ mode = fcntl (oss->fd, F_GETFL);
+ mode &= ~O_NONBLOCK;
+ if (fcntl (oss->fd, F_SETFL, mode) == -1) {
+ /* some drivers do no support unsetting the non-blocking flag, try to
+ * close/open the device then. This is racy but we error out properly. */
+ gst_oss_sink_close (asink);
+ if ((oss->fd = open (oss->device, O_WRONLY, 0)) == -1)
+ goto non_block;
+ }
+
+ tmp = gst_oss_sink_get_format (spec->format);
+ if (tmp == 0)
+ goto wrong_format;
+
+ if (spec->width != 16 && spec->width != 8)
+ goto dodgy_width;
+
+ SET_PARAM (oss, SNDCTL_DSP_SETFMT, tmp, "SETFMT");
+ if (spec->channels == 2)
+ SET_PARAM (oss, SNDCTL_DSP_STEREO, 1, "STEREO");
+ SET_PARAM (oss, SNDCTL_DSP_CHANNELS, spec->channels, "CHANNELS");
+ SET_PARAM (oss, SNDCTL_DSP_SPEED, spec->rate, "SPEED");
+
+ tmp = ilog2 (spec->segsize);
+ tmp = ((spec->segtotal & 0x7fff) << 16) | tmp;
+ GST_DEBUG_OBJECT (oss, "set segsize: %d, segtotal: %d, value: %08x",
+ spec->segsize, spec->segtotal, tmp);
+
+ SET_PARAM (oss, SNDCTL_DSP_SETFRAGMENT, tmp, "SETFRAGMENT");
+ GET_PARAM (oss, SNDCTL_DSP_GETOSPACE, &info, "GETOSPACE");
+
+ spec->segsize = info.fragsize;
+ spec->segtotal = info.fragstotal;
+
+ spec->bytes_per_sample = (spec->width / 8) * spec->channels;
+ oss->bytes_per_sample = (spec->width / 8) * spec->channels;
+
+ GST_DEBUG_OBJECT (oss, "got segsize: %d, segtotal: %d, value: %08x",
+ spec->segsize, spec->segtotal, tmp);
+
+ return TRUE;
+
+ /* ERRORS */
+non_block:
+ {
+ GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, (NULL),
+ ("Unable to set device %s in non blocking mode: %s",
+ oss->device, g_strerror (errno)));
+ return FALSE;
+ }
+wrong_format:
+ {
+ GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, (NULL),
+ ("Unable to get format %d", spec->format));
+ return FALSE;
+ }
+dodgy_width:
+ {
+ GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, (NULL),
+ ("unexpected width %d", spec->width));
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_oss_sink_unprepare (GstAudioSink * asink)
+{
+ /* could do a SNDCTL_DSP_RESET, but the OSS manual recommends a close/open */
+
+ if (!gst_oss_sink_close (asink))
+ goto couldnt_close;
+
+ if (!gst_oss_sink_open (asink))
+ goto couldnt_reopen;
+
+ return TRUE;
+
+ /* ERRORS */
+couldnt_close:
+ {
+ GST_DEBUG_OBJECT (asink, "Could not close the audio device");
+ return FALSE;
+ }
+couldnt_reopen:
+ {
+ GST_DEBUG_OBJECT (asink, "Could not reopen the audio device");
+ return FALSE;
+ }
+}
+
+static guint
+gst_oss_sink_write (GstAudioSink * asink, gpointer data, guint length)
+{
+ return write (GST_OSSSINK (asink)->fd, data, length);
+}
+
+static guint
+gst_oss_sink_delay (GstAudioSink * asink)
+{
+ GstOssSink *oss;
+ gint delay = 0;
+ gint ret;
+
+ oss = GST_OSSSINK (asink);
+
+#ifdef SNDCTL_DSP_GETODELAY
+ ret = ioctl (oss->fd, SNDCTL_DSP_GETODELAY, &delay);
+#else
+ ret = -1;
+#endif
+ if (ret < 0) {
+ audio_buf_info info;
+
+ ret = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &info);
+
+ delay = (ret < 0 ? 0 : (info.fragstotal * info.fragsize) - info.bytes);
+ }
+ return delay / oss->bytes_per_sample;
+}
+
+static void
+gst_oss_sink_reset (GstAudioSink * asink)
+{
+ /* There's nothing we can do here really: OSS can't handle access to the
+ * same device/fd from multiple threads and might deadlock or blow up in
+ * other ways if we try an ioctl SNDCTL_DSP_RESET or similar */
+}
diff --git a/sys/oss/gstosssink.h b/sys/oss/gstosssink.h
new file mode 100644
index 0000000..bb2ca93
--- /dev/null
+++ b/sys/oss/gstosssink.h
@@ -0,0 +1,62 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstosssink.h:
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_OSSSINK_H__
+#define __GST_OSSSINK_H__
+
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosink.h>
+
+#include "gstosshelper.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSSSINK (gst_oss_sink_get_type())
+#define GST_OSSSINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSSSINK,GstOssSink))
+#define GST_OSSSINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSSSINK,GstOssSinkClass))
+#define GST_IS_OSSSINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSSSINK))
+#define GST_IS_OSSSINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSSSINK))
+
+typedef struct _GstOssSink GstOssSink;
+typedef struct _GstOssSinkClass GstOssSinkClass;
+
+struct _GstOssSink {
+ GstAudioSink sink;
+
+ gchar *device;
+ gint fd;
+ gint bytes_per_sample;
+
+ GstCaps *probed_caps;
+};
+
+struct _GstOssSinkClass {
+ GstAudioSinkClass parent_class;
+};
+
+GType gst_oss_sink_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_OSSSINK_H__ */
diff --git a/sys/oss/gstosssrc.c b/sys/oss/gstosssrc.c
new file mode 100644
index 0000000..2bd931b
--- /dev/null
+++ b/sys/oss/gstosssrc.c
@@ -0,0 +1,537 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000,2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstosssrc.c:
+ *
+ * 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-osssrc
+ *
+ * This element lets you record sound using the Open Sound System (OSS).
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * |[
+ * gst-launch -v osssrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=mymusic.ogg
+ * ]| will record sound from your sound card using OSS and encode it to an
+ * Ogg/Vorbis file (this will only work if your mixer settings are right
+ * and the right inputs enabled etc.)
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifdef HAVE_OSS_INCLUDE_IN_SYS
+# include <sys/soundcard.h>
+#else
+# ifdef HAVE_OSS_INCLUDE_IN_ROOT
+# include <soundcard.h>
+# else
+# ifdef HAVE_OSS_INCLUDE_IN_MACHINE
+# include <machine/soundcard.h>
+# else
+# error "What to include?"
+# endif /* HAVE_OSS_INCLUDE_IN_MACHINE */
+# endif /* HAVE_OSS_INCLUDE_IN_ROOT */
+#endif /* HAVE_OSS_INCLUDE_IN_SYS */
+
+#include "gstosssrc.h"
+#include "common.h"
+
+#include <gst/gst-i18n-plugin.h>
+
+GST_DEBUG_CATEGORY_EXTERN (oss_debug);
+#define GST_CAT_DEFAULT oss_debug
+
+#define DEFAULT_DEVICE "/dev/dsp"
+#define DEFAULT_DEVICE_NAME ""
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+ PROP_DEVICE_NAME,
+};
+
+GST_BOILERPLATE_WITH_INTERFACE (GstOssSrc, gst_oss_src, GstAudioSrc,
+ GST_TYPE_AUDIO_SRC, GstMixer, GST_TYPE_MIXER, gst_oss_src_mixer);
+
+GST_IMPLEMENT_OSS_MIXER_METHODS (GstOssSrc, gst_oss_src_mixer);
+
+static void gst_oss_src_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static void gst_oss_src_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+
+static void gst_oss_src_dispose (GObject * object);
+static void gst_oss_src_finalize (GstOssSrc * osssrc);
+
+static GstCaps *gst_oss_src_getcaps (GstBaseSrc * bsrc);
+
+static gboolean gst_oss_src_open (GstAudioSrc * asrc);
+static gboolean gst_oss_src_close (GstAudioSrc * asrc);
+static gboolean gst_oss_src_prepare (GstAudioSrc * asrc,
+ GstRingBufferSpec * spec);
+static gboolean gst_oss_src_unprepare (GstAudioSrc * asrc);
+static guint gst_oss_src_read (GstAudioSrc * asrc, gpointer data, guint length);
+static guint gst_oss_src_delay (GstAudioSrc * asrc);
+static void gst_oss_src_reset (GstAudioSrc * asrc);
+
+
+
+static GstStaticPadTemplate osssrc_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-int, "
+ "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, "
+ "signed = (boolean) { TRUE, FALSE }, "
+ "width = (int) 16, "
+ "depth = (int) 16, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
+ "audio/x-raw-int, "
+ "signed = (boolean) { TRUE, FALSE }, "
+ "width = (int) 8, "
+ "depth = (int) 8, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
+ );
+
+
+static void
+gst_oss_src_dispose (GObject * object)
+{
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_oss_src_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_set_details_simple (element_class, "Audio Source (OSS)",
+ "Source/Audio",
+ "Capture from a sound card via OSS",
+ "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>");
+
+ gst_element_class_add_static_pad_template (element_class,
+ &osssrc_src_factory);
+}
+
+static void
+gst_oss_src_class_init (GstOssSrcClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstBaseSrcClass *gstbasesrc_class;
+ GstAudioSrcClass *gstaudiosrc_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstbasesrc_class = (GstBaseSrcClass *) klass;
+ gstaudiosrc_class = (GstAudioSrcClass *) klass;
+
+ gobject_class->dispose = gst_oss_src_dispose;
+ gobject_class->finalize = (GObjectFinalizeFunc) gst_oss_src_finalize;
+ gobject_class->get_property = gst_oss_src_get_property;
+ gobject_class->set_property = gst_oss_src_set_property;
+
+ gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_oss_src_getcaps);
+
+ gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_oss_src_open);
+ gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_oss_src_prepare);
+ gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_oss_src_unprepare);
+ gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_oss_src_close);
+ gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_oss_src_read);
+ gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_oss_src_delay);
+ gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_oss_src_reset);
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device",
+ "OSS device (usually /dev/dspN)", DEFAULT_DEVICE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
+ g_param_spec_string ("device-name", "Device name",
+ "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+gst_oss_src_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOssSrc *src;
+
+ src = GST_OSS_SRC (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ if (src->device)
+ g_free (src->device);
+ src->device = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_oss_src_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstOssSrc *src;
+
+ src = GST_OSS_SRC (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_value_set_string (value, src->device);
+ break;
+ case PROP_DEVICE_NAME:
+ g_value_set_string (value, src->device_name);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_oss_src_init (GstOssSrc * osssrc, GstOssSrcClass * g_class)
+{
+ const gchar *device;
+
+ GST_DEBUG ("initializing osssrc");
+
+ device = g_getenv ("AUDIODEV");
+ if (device == NULL)
+ device = DEFAULT_DEVICE;
+
+ osssrc->fd = -1;
+ osssrc->device = g_strdup (device);
+ osssrc->device_name = g_strdup (DEFAULT_DEVICE_NAME);
+ osssrc->probed_caps = NULL;
+}
+
+static void
+gst_oss_src_finalize (GstOssSrc * osssrc)
+{
+ g_free (osssrc->device);
+ g_free (osssrc->device_name);
+
+ G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (osssrc));
+}
+
+static GstCaps *
+gst_oss_src_getcaps (GstBaseSrc * bsrc)
+{
+ GstOssSrc *osssrc;
+ GstCaps *caps;
+
+ osssrc = GST_OSS_SRC (bsrc);
+
+ if (osssrc->fd == -1) {
+ GST_DEBUG_OBJECT (osssrc, "device not open, using template caps");
+ return NULL; /* base class will get template caps for us */
+ }
+
+ if (osssrc->probed_caps) {
+ GST_LOG_OBJECT (osssrc, "Returning cached caps");
+ return gst_caps_ref (osssrc->probed_caps);
+ }
+
+ caps = gst_oss_helper_probe_caps (osssrc->fd);
+
+ if (caps) {
+ osssrc->probed_caps = gst_caps_ref (caps);
+ }
+
+ GST_INFO_OBJECT (osssrc, "returning caps %" GST_PTR_FORMAT, caps);
+
+ return caps;
+}
+
+static gint
+ilog2 (gint x)
+{
+ /* well... hacker's delight explains... */
+ x = x | (x >> 1);
+ x = x | (x >> 2);
+ x = x | (x >> 4);
+ x = x | (x >> 8);
+ x = x | (x >> 16);
+ x = x - ((x >> 1) & 0x55555555);
+ x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+ x = (x + (x >> 4)) & 0x0f0f0f0f;
+ x = x + (x >> 8);
+ x = x + (x >> 16);
+ return (x & 0x0000003f) - 1;
+}
+
+static gint
+gst_oss_src_get_format (GstBufferFormat fmt)
+{
+ gint result;
+
+ switch (fmt) {
+ case GST_MU_LAW:
+ result = AFMT_MU_LAW;
+ break;
+ case GST_A_LAW:
+ result = AFMT_A_LAW;
+ break;
+ case GST_IMA_ADPCM:
+ result = AFMT_IMA_ADPCM;
+ break;
+ case GST_U8:
+ result = AFMT_U8;
+ break;
+ case GST_S16_LE:
+ result = AFMT_S16_LE;
+ break;
+ case GST_S16_BE:
+ result = AFMT_S16_BE;
+ break;
+ case GST_S8:
+ result = AFMT_S8;
+ break;
+ case GST_U16_LE:
+ result = AFMT_U16_LE;
+ break;
+ case GST_U16_BE:
+ result = AFMT_U16_BE;
+ break;
+ case GST_MPEG:
+ result = AFMT_MPEG;
+ break;
+ default:
+ result = 0;
+ break;
+ }
+ return result;
+}
+
+static gboolean
+gst_oss_src_open (GstAudioSrc * asrc)
+{
+ GstOssSrc *oss;
+ int mode;
+
+ oss = GST_OSS_SRC (asrc);
+
+ mode = O_RDONLY;
+ mode |= O_NONBLOCK;
+
+ oss->fd = open (oss->device, mode, 0);
+ if (oss->fd == -1) {
+ switch (errno) {
+ case EACCES:
+ goto no_permission;
+ default:
+ goto open_failed;
+ }
+ }
+
+ if (!oss->mixer) {
+ oss->mixer = gst_ossmixer_new ("/dev/mixer", GST_OSS_MIXER_CAPTURE);
+
+ if (oss->mixer) {
+ g_free (oss->device_name);
+ oss->device_name = g_strdup (oss->mixer->cardname);
+ }
+ }
+ return TRUE;
+
+no_permission:
+ {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
+ (_("Could not open audio device for recording. "
+ "You don't have permission to open the device.")),
+ GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+open_failed:
+ {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
+ (_("Could not open audio device for recording.")),
+ ("Unable to open device %s for recording: %s",
+ oss->device, g_strerror (errno)));
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_oss_src_close (GstAudioSrc * asrc)
+{
+ GstOssSrc *oss;
+
+ oss = GST_OSS_SRC (asrc);
+
+ close (oss->fd);
+
+ if (oss->mixer) {
+ gst_ossmixer_free (oss->mixer);
+ oss->mixer = NULL;
+ }
+
+ gst_caps_replace (&oss->probed_caps, NULL);
+
+ return TRUE;
+}
+
+static gboolean
+gst_oss_src_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
+{
+ GstOssSrc *oss;
+ struct audio_buf_info info;
+ int mode;
+ int fmt, tmp;
+
+ oss = GST_OSS_SRC (asrc);
+
+ mode = fcntl (oss->fd, F_GETFL);
+ mode &= ~O_NONBLOCK;
+ if (fcntl (oss->fd, F_SETFL, mode) == -1)
+ goto non_block;
+
+ fmt = gst_oss_src_get_format (spec->format);
+ if (fmt == 0)
+ goto wrong_format;
+
+ tmp = ilog2 (spec->segsize);
+ tmp = ((spec->segtotal & 0x7fff) << 16) | tmp;
+ GST_DEBUG_OBJECT (oss, "set segsize: %d, segtotal: %d, value: %08x",
+ spec->segsize, spec->segtotal, tmp);
+
+ SET_PARAM (oss, SNDCTL_DSP_SETFRAGMENT, tmp, "SETFRAGMENT");
+
+ SET_PARAM (oss, SNDCTL_DSP_RESET, 0, "RESET");
+
+ SET_PARAM (oss, SNDCTL_DSP_SETFMT, fmt, "SETFMT");
+ if (spec->channels == 2)
+ SET_PARAM (oss, SNDCTL_DSP_STEREO, 1, "STEREO");
+ SET_PARAM (oss, SNDCTL_DSP_CHANNELS, spec->channels, "CHANNELS");
+ SET_PARAM (oss, SNDCTL_DSP_SPEED, spec->rate, "SPEED");
+
+ GET_PARAM (oss, SNDCTL_DSP_GETISPACE, &info, "GETISPACE");
+
+ spec->segsize = info.fragsize;
+ spec->segtotal = info.fragstotal;
+
+ if (spec->width != 16 && spec->width != 8)
+ goto dodgy_width;
+
+ spec->bytes_per_sample = (spec->width / 8) * spec->channels;
+ oss->bytes_per_sample = (spec->width / 8) * spec->channels;
+ memset (spec->silence_sample, 0, spec->bytes_per_sample);
+
+ GST_DEBUG_OBJECT (oss, "got segsize: %d, segtotal: %d, value: %08x",
+ spec->segsize, spec->segtotal, tmp);
+
+ return TRUE;
+
+non_block:
+ {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
+ ("Unable to set device %s in non blocking mode: %s",
+ oss->device, g_strerror (errno)), (NULL));
+ return FALSE;
+ }
+wrong_format:
+ {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
+ ("Unable to get format %d", spec->format), (NULL));
+ return FALSE;
+ }
+dodgy_width:
+ {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
+ ("Unexpected width %d", spec->width), (NULL));
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_oss_src_unprepare (GstAudioSrc * asrc)
+{
+ /* could do a SNDCTL_DSP_RESET, but the OSS manual recommends a close/open */
+
+ if (!gst_oss_src_close (asrc))
+ goto couldnt_close;
+
+ if (!gst_oss_src_open (asrc))
+ goto couldnt_reopen;
+
+ return TRUE;
+
+couldnt_close:
+ {
+ GST_DEBUG_OBJECT (asrc, "Could not close the audio device");
+ return FALSE;
+ }
+couldnt_reopen:
+ {
+ GST_DEBUG_OBJECT (asrc, "Could not reopen the audio device");
+ return FALSE;
+ }
+}
+
+static guint
+gst_oss_src_read (GstAudioSrc * asrc, gpointer data, guint length)
+{
+ return read (GST_OSS_SRC (asrc)->fd, data, length);
+}
+
+static guint
+gst_oss_src_delay (GstAudioSrc * asrc)
+{
+ GstOssSrc *oss;
+ gint delay = 0;
+ gint ret;
+
+ oss = GST_OSS_SRC (asrc);
+
+#ifdef SNDCTL_DSP_GETODELAY
+ ret = ioctl (oss->fd, SNDCTL_DSP_GETODELAY, &delay);
+#else
+ ret = -1;
+#endif
+ if (ret < 0) {
+ audio_buf_info info;
+
+ ret = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &info);
+
+ delay = (ret < 0 ? 0 : (info.fragstotal * info.fragsize) - info.bytes);
+ }
+ return delay / oss->bytes_per_sample;
+}
+
+static void
+gst_oss_src_reset (GstAudioSrc * asrc)
+{
+ /* There's nothing we can do here really: OSS can't handle access to the
+ * same device/fd from multiple threads and might deadlock or blow up in
+ * other ways if we try an ioctl SNDCTL_DSP_RESET or similar */
+}
diff --git a/sys/oss/gstosssrc.h b/sys/oss/gstosssrc.h
new file mode 100644
index 0000000..0d14613
--- /dev/null
+++ b/sys/oss/gstosssrc.h
@@ -0,0 +1,67 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstosssrc.h:
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_OSS_SRC_H__
+#define __GST_OSS_SRC_H__
+
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosrc.h>
+
+#include "gstosshelper.h"
+#include "gstossmixer.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSS_SRC (gst_oss_src_get_type())
+#define GST_OSS_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS_SRC,GstOssSrc))
+#define GST_OSS_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS_SRC,GstOssSrcClass))
+#define GST_IS_OSS_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS_SRC))
+#define GST_IS_OSS_SRC_CLASS(klas) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS_SRC))
+
+typedef struct _GstOssSrc GstOssSrc;
+typedef struct _GstOssSrcClass GstOssSrcClass;
+
+struct _GstOssSrc {
+ GstAudioSrc src;
+
+ gint fd;
+ gint bytes_per_sample;
+
+ gchar *device;
+ gchar *device_name;
+
+ GstCaps *probed_caps;
+
+ GstOssMixer *mixer;
+};
+
+struct _GstOssSrcClass {
+ GstAudioSrcClass parent_class;
+};
+
+GType gst_oss_src_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_OSS_SRC_H__ */
diff --git a/sys/oss4/Makefile.am b/sys/oss4/Makefile.am
new file mode 100644
index 0000000..955e903
--- /dev/null
+++ b/sys/oss4/Makefile.am
@@ -0,0 +1,33 @@
+plugin_LTLIBRARIES = libgstoss4audio.la
+
+libgstoss4audio_la_SOURCES = \
+ oss4-audio.c \
+ oss4-mixer.c \
+ oss4-mixer-enum.c \
+ oss4-mixer-slider.c \
+ oss4-mixer-switch.c \
+ oss4-property-probe.c \
+ oss4-sink.c \
+ oss4-source.c
+
+libgstoss4audio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
+libgstoss4audio_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstinterfaces-$(GST_MAJORMINOR) \
+ -lgstaudio-$(GST_MAJORMINOR) \
+ $(GST_LIBS)
+libgstoss4audio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstoss4audio_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = \
+ oss4-audio.h \
+ oss4-mixer.h \
+ oss4-mixer-enum.h \
+ oss4-mixer-slider.h \
+ oss4-mixer-switch.h \
+ oss4-property-probe.h \
+ oss4-sink.h \
+ oss4-soundcard.h \
+ oss4-source.h
+
+
diff --git a/sys/oss4/Makefile.in b/sys/oss4/Makefile.in
new file mode 100644
index 0000000..3cda65b
--- /dev/null
+++ b/sys/oss4/Makefile.in
@@ -0,0 +1,892 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sys/oss4
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
+ $(top_srcdir)/common/m4/as-auto-alt.m4 \
+ $(top_srcdir)/common/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/common/m4/as-gcc-inline-assembly.m4 \
+ $(top_srcdir)/common/m4/as-objc.m4 \
+ $(top_srcdir)/common/m4/as-python.m4 \
+ $(top_srcdir)/common/m4/as-scrub-include.m4 \
+ $(top_srcdir)/common/m4/as-version.m4 \
+ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
+ $(top_srcdir)/common/m4/gst-arch.m4 \
+ $(top_srcdir)/common/m4/gst-args.m4 \
+ $(top_srcdir)/common/m4/gst-check.m4 \
+ $(top_srcdir)/common/m4/gst-default.m4 \
+ $(top_srcdir)/common/m4/gst-dowhile.m4 \
+ $(top_srcdir)/common/m4/gst-error.m4 \
+ $(top_srcdir)/common/m4/gst-feature.m4 \
+ $(top_srcdir)/common/m4/gst-gettext.m4 \
+ $(top_srcdir)/common/m4/gst-glib2.m4 \
+ $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \
+ $(top_srcdir)/common/m4/gst-platform.m4 \
+ $(top_srcdir)/common/m4/gst-plugin-docs.m4 \
+ $(top_srcdir)/common/m4/gst-plugindir.m4 \
+ $(top_srcdir)/common/m4/gst-x11.m4 \
+ $(top_srcdir)/common/m4/gst.m4 \
+ $(top_srcdir)/common/m4/gtk-doc.m4 \
+ $(top_srcdir)/common/m4/orc.m4 $(top_srcdir)/common/m4/pkg.m4 \
+ $(top_srcdir)/m4/aalib.m4 $(top_srcdir)/m4/esd.m4 \
+ $(top_srcdir)/m4/gconf-2.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gst-fionread.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgstoss4audio_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_libgstoss4audio_la_OBJECTS = libgstoss4audio_la-oss4-audio.lo \
+ libgstoss4audio_la-oss4-mixer.lo \
+ libgstoss4audio_la-oss4-mixer-enum.lo \
+ libgstoss4audio_la-oss4-mixer-slider.lo \
+ libgstoss4audio_la-oss4-mixer-switch.lo \
+ libgstoss4audio_la-oss4-property-probe.lo \
+ libgstoss4audio_la-oss4-sink.lo \
+ libgstoss4audio_la-oss4-source.lo
+libgstoss4audio_la_OBJECTS = $(am_libgstoss4audio_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libgstoss4audio_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
+ $(CCLD) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) \
+ $(libgstoss4audio_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libgstoss4audio_la_SOURCES)
+DIST_SOURCES = $(libgstoss4audio_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+AALIB_CFLAGS = @AALIB_CFLAGS@
+AALIB_CONFIG = @AALIB_CONFIG@
+AALIB_LIBS = @AALIB_LIBS@
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+ANNODEX_CFLAGS = @ANNODEX_CFLAGS@
+ANNODEX_LIBS = @ANNODEX_LIBS@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BZ2_LIBS = @BZ2_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_GOBJECT_CFLAGS = @CAIRO_GOBJECT_CFLAGS@
+CAIRO_GOBJECT_LIBS = @CAIRO_GOBJECT_LIBS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@
+DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@
+DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@
+DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@
+DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@
+DIRECTSOUND_CFLAGS = @DIRECTSOUND_CFLAGS@
+DIRECTSOUND_LDFLAGS = @DIRECTSOUND_LDFLAGS@
+DIRECTSOUND_LIBS = @DIRECTSOUND_LIBS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DV1394_CFLAGS = @DV1394_CFLAGS@
+DV1394_LIBS = @DV1394_LIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ERROR_CFLAGS = @ERROR_CFLAGS@
+ERROR_CXXFLAGS = @ERROR_CXXFLAGS@
+ESD_CFLAGS = @ESD_CFLAGS@
+ESD_CONFIG = @ESD_CONFIG@
+ESD_LIBS = @ESD_LIBS@
+EXEEXT = @EXEEXT@
+FFLAGS = @FFLAGS@
+FGREP = @FGREP@
+FLAC_CFLAGS = @FLAC_CFLAGS@
+FLAC_LIBS = @FLAC_LIBS@
+GCONFTOOL = @GCONFTOOL@
+GCONF_CFLAGS = @GCONF_CFLAGS@
+GCONF_LIBS = @GCONF_LIBS@
+GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+GCOV = @GCOV@
+GCOV_CFLAGS = @GCOV_CFLAGS@
+GCOV_LIBS = @GCOV_LIBS@
+GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@
+GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_PREFIX = @GLIB_PREFIX@
+GLIB_REQ = @GLIB_REQ@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@
+GSTPB_PREFIX = @GSTPB_PREFIX@
+GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@
+GST_BASE_CFLAGS = @GST_BASE_CFLAGS@
+GST_BASE_LIBS = @GST_BASE_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_CONTROLLER_CFLAGS = @GST_CONTROLLER_CFLAGS@
+GST_CONTROLLER_LIBS = @GST_CONTROLLER_LIBS@
+GST_CXXFLAGS = @GST_CXXFLAGS@
+GST_GDP_CFLAGS = @GST_GDP_CFLAGS@
+GST_GDP_LIBS = @GST_GDP_LIBS@
+GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@
+GST_LIBS = @GST_LIBS@
+GST_LICENSE = @GST_LICENSE@
+GST_LT_LDFLAGS = @GST_LT_LDFLAGS@
+GST_MAJORMINOR = @GST_MAJORMINOR@
+GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@
+GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@
+GST_PACKAGE_NAME = @GST_PACKAGE_NAME@
+GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@
+GST_PLUGINS_ALL = @GST_PLUGINS_ALL@
+GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@
+GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@
+GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@
+GST_PLUGINS_DIR = @GST_PLUGINS_DIR@
+GST_PLUGINS_SELECTED = @GST_PLUGINS_SELECTED@
+GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@
+GST_PREFIX = @GST_PREFIX@
+GST_TOOLS_DIR = @GST_TOOLS_DIR@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_X11_CFLAGS = @GTK_X11_CFLAGS@
+GTK_X11_LIBS = @GTK_X11_LIBS@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+HAVE_AVC1394 = @HAVE_AVC1394@
+HAVE_BZ2 = @HAVE_BZ2@
+HAVE_CXX = @HAVE_CXX@
+HAVE_DIRECTSOUND = @HAVE_DIRECTSOUND@
+HAVE_GCONFTOOL = @HAVE_GCONFTOOL@
+HAVE_ROM1394 = @HAVE_ROM1394@
+HAVE_SPEEX = @HAVE_SPEEX@
+HAVE_X = @HAVE_X@
+HAVE_XSHM = @HAVE_XSHM@
+HAVE_ZLIB = @HAVE_ZLIB@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JACK_0_120_1_CFLAGS = @JACK_0_120_1_CFLAGS@
+JACK_0_120_1_LIBS = @JACK_0_120_1_LIBS@
+JACK_1_9_7_CFLAGS = @JACK_1_9_7_CFLAGS@
+JACK_1_9_7_LIBS = @JACK_1_9_7_LIBS@
+JACK_CFLAGS = @JACK_CFLAGS@
+JACK_LIBS = @JACK_LIBS@
+JPEG_LIBS = @JPEG_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCACA_CFLAGS = @LIBCACA_CFLAGS@
+LIBCACA_LIBS = @LIBCACA_LIBS@
+LIBDV_CFLAGS = @LIBDV_CFLAGS@
+LIBDV_LIBS = @LIBDV_LIBS@
+LIBICONV = @LIBICONV@
+LIBIEC61883_CFLAGS = @LIBIEC61883_CFLAGS@
+LIBIEC61883_LIBS = @LIBIEC61883_LIBS@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBPNG_CFLAGS = @LIBPNG_CFLAGS@
+LIBPNG_LIBS = @LIBPNG_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBV4L2_CFLAGS = @LIBV4L2_CFLAGS@
+LIBV4L2_LIBS = @LIBV4L2_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCALEDIR = @LOCALEDIR@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJC_LDFLAGS = @OBJC_LDFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORCC = @ORCC@
+ORCC_FLAGS = @ORCC_FLAGS@
+ORC_CFLAGS = @ORC_CFLAGS@
+ORC_LIBS = @ORC_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@
+PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PLUGINDIR = @PLUGINDIR@
+POSUB = @POSUB@
+PROFILE_CFLAGS = @PROFILE_CFLAGS@
+PULSE_0_9_20_CFLAGS = @PULSE_0_9_20_CFLAGS@
+PULSE_0_9_20_LIBS = @PULSE_0_9_20_LIBS@
+PULSE_1_0_CFLAGS = @PULSE_1_0_CFLAGS@
+PULSE_1_0_LIBS = @PULSE_1_0_LIBS@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RAW1394_CFLAGS = @RAW1394_CFLAGS@
+RAW1394_LIBS = @RAW1394_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHOUT2_CFLAGS = @SHOUT2_CFLAGS@
+SHOUT2_LIBS = @SHOUT2_LIBS@
+SOUP_CFLAGS = @SOUP_CFLAGS@
+SOUP_LIBS = @SOUP_LIBS@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+TAGLIB_CFLAGS = @TAGLIB_CFLAGS@
+TAGLIB_CXXFLAGS = @TAGLIB_CXXFLAGS@
+TAGLIB_LIBS = @TAGLIB_LIBS@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VALGRIND_PATH = @VALGRIND_PATH@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
+WAVPACK_LIBS = @WAVPACK_LIBS@
+WIN32_LIBS = @WIN32_LIBS@
+XDAMAGE_CFLAGS = @XDAMAGE_CFLAGS@
+XDAMAGE_LIBS = @XDAMAGE_LIBS@
+XFIXES_CFLAGS = @XFIXES_CFLAGS@
+XFIXES_LIBS = @XFIXES_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+XMKMF = @XMKMF@
+XSHM_LIBS = @XSHM_LIBS@
+XVIDEO_LIBS = @XVIDEO_LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = libgstoss4audio.la
+libgstoss4audio_la_SOURCES = \
+ oss4-audio.c \
+ oss4-mixer.c \
+ oss4-mixer-enum.c \
+ oss4-mixer-slider.c \
+ oss4-mixer-switch.c \
+ oss4-property-probe.c \
+ oss4-sink.c \
+ oss4-source.c
+
+libgstoss4audio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
+libgstoss4audio_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstinterfaces-$(GST_MAJORMINOR) \
+ -lgstaudio-$(GST_MAJORMINOR) \
+ $(GST_LIBS)
+
+libgstoss4audio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstoss4audio_la_LIBTOOLFLAGS = --tag=disable-static
+noinst_HEADERS = \
+ oss4-audio.h \
+ oss4-mixer.h \
+ oss4-mixer-enum.h \
+ oss4-mixer-slider.h \
+ oss4-mixer-switch.h \
+ oss4-property-probe.h \
+ oss4-sink.h \
+ oss4-soundcard.h \
+ oss4-source.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sys/oss4/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu sys/oss4/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgstoss4audio.la: $(libgstoss4audio_la_OBJECTS) $(libgstoss4audio_la_DEPENDENCIES) $(EXTRA_libgstoss4audio_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgstoss4audio_la_LINK) -rpath $(plugindir) $(libgstoss4audio_la_OBJECTS) $(libgstoss4audio_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstoss4audio_la-oss4-audio.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstoss4audio_la-oss4-mixer-enum.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstoss4audio_la-oss4-mixer-slider.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstoss4audio_la-oss4-mixer-switch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstoss4audio_la-oss4-mixer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstoss4audio_la-oss4-property-probe.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstoss4audio_la-oss4-sink.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstoss4audio_la-oss4-source.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libgstoss4audio_la-oss4-audio.lo: oss4-audio.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -MT libgstoss4audio_la-oss4-audio.lo -MD -MP -MF $(DEPDIR)/libgstoss4audio_la-oss4-audio.Tpo -c -o libgstoss4audio_la-oss4-audio.lo `test -f 'oss4-audio.c' || echo '$(srcdir)/'`oss4-audio.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstoss4audio_la-oss4-audio.Tpo $(DEPDIR)/libgstoss4audio_la-oss4-audio.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oss4-audio.c' object='libgstoss4audio_la-oss4-audio.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -c -o libgstoss4audio_la-oss4-audio.lo `test -f 'oss4-audio.c' || echo '$(srcdir)/'`oss4-audio.c
+
+libgstoss4audio_la-oss4-mixer.lo: oss4-mixer.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -MT libgstoss4audio_la-oss4-mixer.lo -MD -MP -MF $(DEPDIR)/libgstoss4audio_la-oss4-mixer.Tpo -c -o libgstoss4audio_la-oss4-mixer.lo `test -f 'oss4-mixer.c' || echo '$(srcdir)/'`oss4-mixer.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstoss4audio_la-oss4-mixer.Tpo $(DEPDIR)/libgstoss4audio_la-oss4-mixer.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oss4-mixer.c' object='libgstoss4audio_la-oss4-mixer.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -c -o libgstoss4audio_la-oss4-mixer.lo `test -f 'oss4-mixer.c' || echo '$(srcdir)/'`oss4-mixer.c
+
+libgstoss4audio_la-oss4-mixer-enum.lo: oss4-mixer-enum.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -MT libgstoss4audio_la-oss4-mixer-enum.lo -MD -MP -MF $(DEPDIR)/libgstoss4audio_la-oss4-mixer-enum.Tpo -c -o libgstoss4audio_la-oss4-mixer-enum.lo `test -f 'oss4-mixer-enum.c' || echo '$(srcdir)/'`oss4-mixer-enum.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstoss4audio_la-oss4-mixer-enum.Tpo $(DEPDIR)/libgstoss4audio_la-oss4-mixer-enum.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oss4-mixer-enum.c' object='libgstoss4audio_la-oss4-mixer-enum.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -c -o libgstoss4audio_la-oss4-mixer-enum.lo `test -f 'oss4-mixer-enum.c' || echo '$(srcdir)/'`oss4-mixer-enum.c
+
+libgstoss4audio_la-oss4-mixer-slider.lo: oss4-mixer-slider.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -MT libgstoss4audio_la-oss4-mixer-slider.lo -MD -MP -MF $(DEPDIR)/libgstoss4audio_la-oss4-mixer-slider.Tpo -c -o libgstoss4audio_la-oss4-mixer-slider.lo `test -f 'oss4-mixer-slider.c' || echo '$(srcdir)/'`oss4-mixer-slider.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstoss4audio_la-oss4-mixer-slider.Tpo $(DEPDIR)/libgstoss4audio_la-oss4-mixer-slider.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oss4-mixer-slider.c' object='libgstoss4audio_la-oss4-mixer-slider.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -c -o libgstoss4audio_la-oss4-mixer-slider.lo `test -f 'oss4-mixer-slider.c' || echo '$(srcdir)/'`oss4-mixer-slider.c
+
+libgstoss4audio_la-oss4-mixer-switch.lo: oss4-mixer-switch.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -MT libgstoss4audio_la-oss4-mixer-switch.lo -MD -MP -MF $(DEPDIR)/libgstoss4audio_la-oss4-mixer-switch.Tpo -c -o libgstoss4audio_la-oss4-mixer-switch.lo `test -f 'oss4-mixer-switch.c' || echo '$(srcdir)/'`oss4-mixer-switch.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstoss4audio_la-oss4-mixer-switch.Tpo $(DEPDIR)/libgstoss4audio_la-oss4-mixer-switch.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oss4-mixer-switch.c' object='libgstoss4audio_la-oss4-mixer-switch.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -c -o libgstoss4audio_la-oss4-mixer-switch.lo `test -f 'oss4-mixer-switch.c' || echo '$(srcdir)/'`oss4-mixer-switch.c
+
+libgstoss4audio_la-oss4-property-probe.lo: oss4-property-probe.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -MT libgstoss4audio_la-oss4-property-probe.lo -MD -MP -MF $(DEPDIR)/libgstoss4audio_la-oss4-property-probe.Tpo -c -o libgstoss4audio_la-oss4-property-probe.lo `test -f 'oss4-property-probe.c' || echo '$(srcdir)/'`oss4-property-probe.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstoss4audio_la-oss4-property-probe.Tpo $(DEPDIR)/libgstoss4audio_la-oss4-property-probe.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oss4-property-probe.c' object='libgstoss4audio_la-oss4-property-probe.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -c -o libgstoss4audio_la-oss4-property-probe.lo `test -f 'oss4-property-probe.c' || echo '$(srcdir)/'`oss4-property-probe.c
+
+libgstoss4audio_la-oss4-sink.lo: oss4-sink.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -MT libgstoss4audio_la-oss4-sink.lo -MD -MP -MF $(DEPDIR)/libgstoss4audio_la-oss4-sink.Tpo -c -o libgstoss4audio_la-oss4-sink.lo `test -f 'oss4-sink.c' || echo '$(srcdir)/'`oss4-sink.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstoss4audio_la-oss4-sink.Tpo $(DEPDIR)/libgstoss4audio_la-oss4-sink.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oss4-sink.c' object='libgstoss4audio_la-oss4-sink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -c -o libgstoss4audio_la-oss4-sink.lo `test -f 'oss4-sink.c' || echo '$(srcdir)/'`oss4-sink.c
+
+libgstoss4audio_la-oss4-source.lo: oss4-source.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -MT libgstoss4audio_la-oss4-source.lo -MD -MP -MF $(DEPDIR)/libgstoss4audio_la-oss4-source.Tpo -c -o libgstoss4audio_la-oss4-source.lo `test -f 'oss4-source.c' || echo '$(srcdir)/'`oss4-source.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstoss4audio_la-oss4-source.Tpo $(DEPDIR)/libgstoss4audio_la-oss4-source.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oss4-source.c' object='libgstoss4audio_la-oss4-source.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstoss4audio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstoss4audio_la_CFLAGS) $(CFLAGS) -c -o libgstoss4audio_la-oss4-source.lo `test -f 'oss4-source.c' || echo '$(srcdir)/'`oss4-source.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sys/oss4/oss4-audio.c b/sys/oss4/oss4-audio.c
new file mode 100644
index 0000000..09f8495
--- /dev/null
+++ b/sys/oss4/oss4-audio.c
@@ -0,0 +1,714 @@
+/* GStreamer OSS4 audio plugin
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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 <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "gst/gst-i18n-plugin.h"
+#include <gst/audio/multichannel.h>
+
+#include "oss4-audio.h"
+#include "oss4-mixer.h"
+#include "oss4-property-probe.h"
+#include "oss4-sink.h"
+#include "oss4-source.h"
+#include "oss4-soundcard.h"
+
+GST_DEBUG_CATEGORY (oss4mixer_debug);
+GST_DEBUG_CATEGORY (oss4sink_debug);
+GST_DEBUG_CATEGORY (oss4src_debug);
+GST_DEBUG_CATEGORY (oss4_debug);
+
+#define GST_CAT_DEFAULT oss4_debug
+
+typedef struct
+{
+ const GstBufferFormat gst_fmt;
+ const gint oss_fmt;
+ const gchar name[16];
+ const gint depth;
+ const gint width;
+ const gint endianness;
+ const gboolean signedness;
+} GstOss4AudioFormat;
+
+/* *INDENT-OFF* */
+static const GstOss4AudioFormat fmt_map[] = {
+ /* note: keep sorted by preference, prefered formats first */
+ {
+ GST_MU_LAW, AFMT_MU_LAW, "audio/x-mulaw", 0, 0, 0, FALSE}, {
+ GST_A_LAW, AFMT_A_LAW, "audio/x-alaw", 0, 0, 0, FALSE}, {
+ GST_S32_LE, AFMT_S32_LE, "audio/x-raw-int", 32, 32, G_LITTLE_ENDIAN, TRUE}, {
+ GST_S32_BE, AFMT_S32_BE, "audio/x-raw-int", 32, 32, G_BIG_ENDIAN, TRUE}, {
+ GST_S24_LE, AFMT_S24_LE, "audio/x-raw-int", 24, 32, G_LITTLE_ENDIAN, TRUE}, {
+ GST_S24_BE, AFMT_S24_BE, "audio/x-raw-int", 24, 32, G_BIG_ENDIAN, TRUE}, {
+ GST_S24_3LE, AFMT_S24_PACKED, "audio/x-raw-int", 24, 24, G_LITTLE_ENDIAN,
+ TRUE}, {
+ GST_S16_LE, AFMT_S16_LE, "audio/x-raw-int", 16, 16, G_LITTLE_ENDIAN, TRUE}, {
+ GST_S16_BE, AFMT_S16_BE, "audio/x-raw-int", 16, 16, G_BIG_ENDIAN, TRUE}, {
+ GST_U16_LE, AFMT_U16_LE, "audio/x-raw-int", 16, 16, G_LITTLE_ENDIAN, FALSE}, {
+ GST_U16_BE, AFMT_U16_BE, "audio/x-raw-int", 16, 16, G_BIG_ENDIAN, FALSE}, {
+ GST_S8, AFMT_S8, "audio/x-raw-int", 8, 8, 0, TRUE}, {
+ GST_U8, AFMT_U8, "audio/x-raw-int", 8, 8, 0, FALSE}
+};
+/* *INDENT-ON* */
+
+/* formats we assume the OSS4 layer can always handle and convert internally */
+#define CONVERTIBLE_FORMATS ( \
+ AFMT_MU_LAW | AFMT_A_LAW | \
+ AFMT_S32_LE | AFMT_S32_BE | \
+ AFMT_S24_LE | AFMT_S24_BE | \
+ AFMT_S24_PACKED | \
+ AFMT_S16_LE | AFMT_S16_BE | \
+ AFMT_U16_LE | AFMT_U16_BE | \
+ AFMT_S8 | AFMT_U8 )
+
+static void
+gst_oss4_append_format_to_caps (const GstOss4AudioFormat * fmt, GstCaps * caps)
+{
+ GstStructure *s;
+
+ s = gst_structure_empty_new (fmt->name);
+ if (fmt->width != 0 && fmt->depth != 0) {
+ gst_structure_set (s, "width", G_TYPE_INT, fmt->width, "depth", G_TYPE_INT,
+ fmt->depth, "signed", G_TYPE_BOOLEAN, fmt->signedness, NULL);
+ }
+ if (fmt->endianness != 0) {
+ gst_structure_set (s, "endianness", G_TYPE_INT, fmt->endianness, NULL);
+ }
+ gst_caps_append_structure (caps, s);
+}
+
+static gint
+gst_oss4_audio_get_oss_format (GstBufferFormat fmt)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) {
+ if (fmt_map[i].gst_fmt == fmt)
+ return fmt_map[i].oss_fmt;
+ }
+ return 0;
+}
+
+/* These are pretty random */
+#define GST_OSS4_MIN_SAMPLE_RATE 1
+#define GST_OSS4_MAX_SAMPLE_RATE 192000
+
+static gboolean
+gst_oss4_audio_detect_rates (GstObject * obj, oss_audioinfo * ai,
+ GstCaps * caps)
+{
+ GValue val = { 0, };
+ int minrate, maxrate, i;
+
+ minrate = ai->min_rate;
+ maxrate = ai->max_rate;
+
+ /* sanity check */
+ if (minrate > maxrate) {
+ GST_WARNING_OBJECT (obj, "min_rate %d > max_rate %d (buggy driver?)",
+ minrate, maxrate);
+ maxrate = ai->min_rate; /* swap */
+ minrate = ai->max_rate;
+ }
+
+ /* limit to something sensible */
+ if (minrate < GST_OSS4_MIN_SAMPLE_RATE)
+ minrate = GST_OSS4_MIN_SAMPLE_RATE;
+ if (maxrate > GST_OSS4_MAX_SAMPLE_RATE)
+ maxrate = GST_OSS4_MAX_SAMPLE_RATE;
+
+ if (maxrate < GST_OSS4_MIN_SAMPLE_RATE) {
+ GST_WARNING_OBJECT (obj, "max_rate < %d, which makes no sense",
+ GST_OSS4_MIN_SAMPLE_RATE);
+ return FALSE;
+ }
+
+ GST_LOG_OBJECT (obj, "min_rate %d, max_rate %d (originally: %d, %d)",
+ minrate, maxrate, ai->min_rate, ai->max_rate);
+
+ if ((ai->caps & PCM_CAP_FREERATE)) {
+ GST_LOG_OBJECT (obj, "device supports any sample rate between min and max");
+ if (minrate == maxrate) {
+ g_value_init (&val, G_TYPE_INT);
+ g_value_set_int (&val, maxrate);
+ } else {
+ g_value_init (&val, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&val, minrate, maxrate);
+ }
+ } else {
+ GST_LOG_OBJECT (obj, "%d sample rates:", ai->nrates);
+ g_value_init (&val, GST_TYPE_LIST);
+ for (i = 0; i < ai->nrates; ++i) {
+ GST_LOG_OBJECT (obj, " rate: %d", ai->rates[i]);
+
+ if (ai->rates[i] >= minrate && ai->rates[i] <= maxrate) {
+ GValue rate_val = { 0, };
+
+ g_value_init (&rate_val, G_TYPE_INT);
+ g_value_set_int (&rate_val, ai->rates[i]);
+ gst_value_list_append_value (&val, &rate_val);
+ g_value_unset (&rate_val);
+ }
+ }
+
+ if (gst_value_list_get_size (&val) == 0) {
+ g_value_unset (&val);
+ return FALSE;
+ }
+ }
+
+ for (i = 0; i < gst_caps_get_size (caps); ++i) {
+ GstStructure *s;
+
+ s = gst_caps_get_structure (caps, i);
+ gst_structure_set_value (s, "rate", &val);
+ }
+
+ g_value_unset (&val);
+
+ return TRUE;
+}
+
+static void
+gst_oss4_audio_add_channel_layout (GstObject * obj, guint64 layout,
+ guint num_channels, GstStructure * s)
+{
+ const GstAudioChannelPosition pos_map[16] = {
+ GST_AUDIO_CHANNEL_POSITION_NONE, /* 0 = dunno */
+ GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, /* 1 = left */
+ GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, /* 2 = right */
+ GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, /* 3 = center */
+ GST_AUDIO_CHANNEL_POSITION_LFE, /* 4 = lfe */
+ GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, /* 5 = left surround */
+ GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, /* 6 = right surround */
+ GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, /* 7 = left rear */
+ GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, /* 8 = right rear */
+ GST_AUDIO_CHANNEL_POSITION_NONE,
+ GST_AUDIO_CHANNEL_POSITION_NONE,
+ GST_AUDIO_CHANNEL_POSITION_NONE,
+ GST_AUDIO_CHANNEL_POSITION_NONE,
+ GST_AUDIO_CHANNEL_POSITION_NONE,
+ GST_AUDIO_CHANNEL_POSITION_NONE,
+ GST_AUDIO_CHANNEL_POSITION_NONE
+ };
+ GstAudioChannelPosition ch_layout[8] = { 0, };
+ guint speaker_pos; /* speaker position as defined by OSS */
+ guint i;
+
+ g_return_if_fail (num_channels <= G_N_ELEMENTS (ch_layout));
+
+ for (i = 0; i < num_channels; ++i) {
+ /* layout contains up to 16 speaker positions, with each taking up 4 bits */
+ speaker_pos = (guint) ((layout >> (i * 4)) & 0x0f);
+
+ /* if it's a channel position that's unknown to us, set all to NONE and
+ * bail out */
+ if (G_UNLIKELY (pos_map[speaker_pos] == GST_AUDIO_CHANNEL_POSITION_NONE))
+ goto no_layout;
+
+ ch_layout[i] = pos_map[speaker_pos];
+ }
+ gst_audio_set_channel_positions (s, ch_layout);
+ return;
+
+no_layout:
+ {
+ /* only warn if it's really unknown, position 0 is ok and represents NONE
+ * (in which case we also just set all others to NONE ignoring the other
+ * positions in the OSS-given layout, because that's what we currently
+ * require in GStreamer) */
+ if (speaker_pos != 0) {
+ GST_WARNING_OBJECT (obj, "unknown OSS channel position %x", ch_layout[i]);
+ }
+ for (i = 0; i < num_channels; ++i) {
+ ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
+ }
+ gst_audio_set_channel_positions (s, ch_layout);
+ return;
+ }
+}
+
+/* arbitrary max. limit */
+#define GST_OSS4_MIN_CHANNELS 1
+#define GST_OSS4_MAX_CHANNELS 4096
+
+/* takes ownership of the input caps */
+static GstCaps *
+gst_oss4_audio_detect_channels (GstObject * obj, int fd, oss_audioinfo * ai,
+ GstCaps * in_caps)
+{
+ const gchar *forced_layout;
+ GstStructure *s = NULL;
+ guint64 layout = 0;
+ GstCaps *chan_caps = NULL;
+ GstCaps *out_caps = NULL;
+ int minchans, maxchans;
+ int c, i, j;
+
+ /* GST_OSS4_CHANNEL_LAYOUT environment variable: may be used to force a
+ * particular channel layout (if it contains an odd number of channel
+ * positions it will also make us advertise a channel layout for that
+ * channel count, even if we'd usually skip it; this is especially useful
+ * for folks with 2.1 speakers, I guess) */
+ forced_layout = g_getenv ("GST_OSS4_CHANNEL_LAYOUT");
+
+ minchans = ai->min_channels;
+ maxchans = ai->max_channels;
+
+ /* sanity check */
+ if (minchans > maxchans) {
+ GST_WARNING_OBJECT (obj, "min_chans %d > max_chans %d (buggy driver?)",
+ minchans, maxchans);
+ maxchans = ai->min_channels; /* swap */
+ minchans = ai->max_channels;
+ }
+
+ /* limit to something sensible */
+ if (minchans < GST_OSS4_MIN_CHANNELS)
+ minchans = GST_OSS4_MIN_CHANNELS;
+ if (maxchans > GST_OSS4_MAX_CHANNELS)
+ maxchans = GST_OSS4_MAX_CHANNELS;
+
+ if (maxchans < GST_OSS4_MIN_CHANNELS) {
+ GST_WARNING_OBJECT (obj, "max_chans < %d, which makes no sense",
+ GST_OSS4_MIN_CHANNELS);
+ gst_caps_unref (in_caps);
+ return NULL;
+ }
+
+ GST_LOG_OBJECT (obj, "min_channels %d, max_channels %d (originally: %d, %d)",
+ minchans, maxchans, ai->min_channels, ai->max_channels);
+
+ chan_caps = gst_caps_new_empty ();
+
+ /* first do the simple cases: mono + stereo (channel layout implied) */
+ if (minchans == 1 && maxchans == 1)
+ s = gst_structure_new ("x", "channels", G_TYPE_INT, 1, NULL);
+ else if (minchans == 2 && maxchans >= 2)
+ s = gst_structure_new ("x", "channels", G_TYPE_INT, 2, NULL);
+ else if (minchans == 1 && maxchans >= 2)
+ s = gst_structure_new ("x", "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
+ gst_caps_append_structure (chan_caps, s);
+ s = NULL;
+
+ /* TODO: we assume all drivers use a left/right layout for stereo here */
+ if (maxchans <= 2)
+ goto done;
+
+ if (ioctl (fd, SNDCTL_DSP_GET_CHNORDER, &layout) == -1) {
+ GST_WARNING_OBJECT (obj, "couldn't query channel layout, assuming default");
+ layout = CHNORDER_NORMAL;
+ }
+ GST_DEBUG_OBJECT (obj, "channel layout: %08" G_GINT64_MODIFIER "x", layout);
+
+ /* e.g. forced 2.1 layout would be GST_OSS4_CHANNEL_LAYOUT=421 */
+ if (forced_layout != NULL && *forced_layout != '\0') {
+ guint layout_len;
+
+ layout_len = strlen (forced_layout);
+ if (layout_len >= minchans && layout_len <= maxchans) {
+ layout = g_ascii_strtoull (forced_layout, NULL, 16);
+ maxchans = layout_len;
+ GST_DEBUG_OBJECT (obj, "forced channel layout: %08" G_GINT64_MODIFIER "x"
+ " ('%s'), maxchans now %d", layout, forced_layout, maxchans);
+ } else {
+ GST_WARNING_OBJECT (obj, "ignoring forced channel layout: layout has %d "
+ "channel positions but maxchans is %d", layout_len, maxchans);
+ }
+ }
+
+ /* need to advertise channel layouts for anything >2 and <=8 channels */
+ for (c = MAX (3, minchans); c <= MIN (maxchans, 8); c++) {
+ /* "The min_channels and max_channels fields define the limits for the
+ * number of channels. However some devices don't support all channels
+ * within this range. It's possible that the odd values (3, 5, 7, 9, etc).
+ * are not supported. There is currently no way to check for this other
+ * than checking if SNDCTL_DSP_CHANNELS accepts the requested value.
+ * Another approach is trying to avoid using odd number of channels."
+ *
+ * So, we don't know for sure if these odd values are supported:
+ */
+ if ((c == 3 || c == 5 || c == 7) && (c != maxchans)) {
+ GST_LOG_OBJECT (obj, "not adding layout with %d channels", c);
+ continue;
+ }
+
+ s = gst_structure_new ("x", "channels", G_TYPE_INT, c, NULL);
+ gst_oss4_audio_add_channel_layout (obj, layout, c, s);
+ GST_LOG_OBJECT (obj, "c=%u, appending struct %" GST_PTR_FORMAT, c, s);
+ gst_caps_append_structure (chan_caps, s);
+ s = NULL;
+ }
+
+ if (maxchans <= 8)
+ goto done;
+
+ /* for everything >8 channels, CHANNEL_POSITION_NONE is implied. */
+ if (minchans == maxchans || maxchans == 9) {
+ s = gst_structure_new ("x", "channels", G_TYPE_INT, maxchans, NULL);
+ } else {
+ s = gst_structure_new ("x", "channels", GST_TYPE_INT_RANGE,
+ MAX (9, minchans), maxchans, NULL);
+ }
+ gst_caps_append_structure (chan_caps, s);
+ s = NULL;
+
+done:
+
+ GST_LOG_OBJECT (obj, "channel structures: %" GST_PTR_FORMAT, chan_caps);
+
+ out_caps = gst_caps_new_empty ();
+
+ /* combine each structure in the input caps with each channel caps struct */
+ for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
+ const GstStructure *in_s;
+
+ in_s = gst_caps_get_structure (in_caps, i);
+
+ for (j = 0; j < gst_caps_get_size (chan_caps); ++j) {
+ const GstStructure *chan_s;
+ const GValue *val;
+
+ s = gst_structure_copy (in_s);
+ chan_s = gst_caps_get_structure (chan_caps, j);
+ if ((val = gst_structure_get_value (chan_s, "channels")))
+ gst_structure_set_value (s, "channels", val);
+ if ((val = gst_structure_get_value (chan_s, "channel-positions")))
+ gst_structure_set_value (s, "channel-positions", val);
+
+ gst_caps_append_structure (out_caps, s);
+ s = NULL;
+ }
+ }
+
+ gst_caps_unref (in_caps);
+ gst_caps_unref (chan_caps);
+ return out_caps;
+}
+
+GstCaps *
+gst_oss4_audio_probe_caps (GstObject * obj, int fd)
+{
+ oss_audioinfo ai = { 0, };
+ gboolean output;
+ GstCaps *caps;
+ int nonnative_formats = 0;
+ int formats, i;
+
+ output = GST_IS_OSS4_SINK (obj);
+
+ /* -1 = get info for currently open device (fd). This will fail with
+ * OSS build <= 1013 because of a bug in OSS */
+ ai.dev = -1;
+ if (ioctl (fd, SNDCTL_ENGINEINFO, &ai) == -1)
+ goto engineinfo_failed;
+
+ formats = (output) ? ai.oformats : ai.iformats;
+
+ GST_LOG_OBJECT (obj, "%s formats : 0x%08x", (output) ? "out" : "in", formats);
+
+ caps = gst_caps_new_empty ();
+
+ /* first list all the formats natively supported */
+ for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) {
+ if ((formats & fmt_map[i].oss_fmt)) {
+ gst_oss4_append_format_to_caps (&fmt_map[i], caps);
+ } else if ((fmt_map[i].oss_fmt & CONVERTIBLE_FORMATS)) {
+ nonnative_formats |= fmt_map[i].oss_fmt;
+ }
+ }
+
+ GST_LOG_OBJECT (obj, "adding non-native %s formats : 0x%08x",
+ (output) ? "out" : "in", nonnative_formats);
+
+ /* now append non-native formats for which conversion would be needed */
+ for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) {
+ if ((nonnative_formats & fmt_map[i].oss_fmt)) {
+ gst_oss4_append_format_to_caps (&fmt_map[i], caps);
+ }
+ }
+
+ gst_caps_do_simplify (caps);
+ GST_LOG_OBJECT (obj, "formats: %" GST_PTR_FORMAT, caps);
+
+ if (!gst_oss4_audio_detect_rates (obj, &ai, caps))
+ goto detect_rates_failed;
+
+ caps = gst_oss4_audio_detect_channels (obj, fd, &ai, caps);
+ if (caps == NULL)
+ goto detect_channels_failed;
+
+ GST_LOG_OBJECT (obj, "probed caps: %" GST_PTR_FORMAT, caps);
+
+ return caps;
+
+/* ERRORS */
+engineinfo_failed:
+ {
+ GST_WARNING ("ENGINEINFO supported formats probe failed: %s",
+ g_strerror (errno));
+ return NULL;
+ }
+detect_rates_failed:
+ {
+ GST_WARNING_OBJECT (obj, "failed to detect supported sample rates");
+ gst_caps_unref (caps);
+ return NULL;
+ }
+detect_channels_failed:
+ {
+ GST_WARNING_OBJECT (obj, "failed to detect supported channels");
+ gst_caps_unref (caps);
+ return NULL;
+ }
+}
+
+GstCaps *
+gst_oss4_audio_get_template_caps (void)
+{
+ GstCaps *caps;
+ gint i;
+
+ caps = gst_caps_new_empty ();
+
+ for (i = 0; i < G_N_ELEMENTS (fmt_map); ++i) {
+ gst_oss4_append_format_to_caps (&fmt_map[i], caps);
+ }
+
+ gst_caps_do_simplify (caps);
+
+ for (i = 0; i < gst_caps_get_size (caps); ++i) {
+ GstStructure *s;
+
+ s = gst_caps_get_structure (caps, i);
+ gst_structure_set (s, "rate", GST_TYPE_INT_RANGE, GST_OSS4_MIN_SAMPLE_RATE,
+ GST_OSS4_MAX_SAMPLE_RATE, "channels", GST_TYPE_INT_RANGE,
+ GST_OSS4_MIN_CHANNELS, GST_OSS4_MAX_CHANNELS, NULL);
+ }
+
+ return caps;
+}
+
+/* called by gst_oss4_sink_prepare() and gst_oss4_source_prepare() */
+gboolean
+gst_oss4_audio_set_format (GstObject * obj, int fd, GstRingBufferSpec * spec)
+{
+ struct audio_buf_info info = { 0, };
+ int fmt, chans, rate;
+
+ fmt = gst_oss4_audio_get_oss_format (spec->format);
+ if (fmt == 0)
+ goto wrong_format;
+
+ if (spec->type == GST_BUFTYPE_LINEAR && spec->width != 32 &&
+ spec->width != 24 && spec->width != 16 && spec->width != 8) {
+ goto dodgy_width;
+ }
+
+ /* format */
+ GST_LOG_OBJECT (obj, "setting format: %d", fmt);
+ if (ioctl (fd, SNDCTL_DSP_SETFMT, &fmt) == -1)
+ goto set_format_failed;
+
+ /* channels */
+ GST_LOG_OBJECT (obj, "setting channels: %d", spec->channels);
+ chans = spec->channels;
+ if (ioctl (fd, SNDCTL_DSP_CHANNELS, &chans) == -1)
+ goto set_channels_failed;
+
+ /* rate */
+ GST_LOG_OBJECT (obj, "setting rate: %d", spec->rate);
+ rate = spec->rate;
+ if (ioctl (fd, SNDCTL_DSP_SPEED, &rate) == -1)
+ goto set_rate_failed;
+
+ GST_DEBUG_OBJECT (obj, "effective format : %d", fmt);
+ GST_DEBUG_OBJECT (obj, "effective channels : %d", chans);
+ GST_DEBUG_OBJECT (obj, "effective rate : %d", rate);
+
+ /* make sure format, channels, and rate are the ones we requested */
+ if (fmt != gst_oss4_audio_get_oss_format (spec->format) ||
+ chans != spec->channels || rate != spec->rate) {
+ /* This shouldn't happen, but hey */
+ goto format_not_what_was_requested;
+ }
+
+ if (GST_IS_OSS4_SOURCE (obj)) {
+ if (ioctl (fd, SNDCTL_DSP_GETISPACE, &info) == -1)
+ goto get_ispace_failed;
+ } else {
+ if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
+ goto get_ospace_failed;
+ }
+
+ spec->segsize = info.fragsize;
+
+ /* we add some extra fragments -- this helps us account for delays due to
+ * conversion buffer, streams queueing, etc. It is important that these
+ * be taken into account because otherwise the delay counter can wind up
+ * being too large, and the buffer will wrap. */
+ spec->segtotal = info.fragstotal + 4;
+
+ spec->bytes_per_sample = (spec->width / 8) * spec->channels;
+
+ GST_DEBUG_OBJECT (obj, "got segsize: %d, segtotal: %d, value: %08x",
+ spec->segsize, spec->segtotal, info.fragsize);
+
+ return TRUE;
+
+/* ERRORS */
+wrong_format:
+ {
+ GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
+ ("Unable to get format %d", spec->format));
+ return FALSE;
+ }
+dodgy_width:
+ {
+ GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
+ ("unexpected width %d", spec->width));
+ return FALSE;
+ }
+set_format_failed:
+ {
+ GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
+ ("DSP_SETFMT(%d) failed: %s", fmt, g_strerror (errno)));
+ return FALSE;
+ }
+set_channels_failed:
+ {
+ GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
+ ("DSP_CHANNELS(%d) failed: %s", chans, g_strerror (errno)));
+ return FALSE;
+ }
+set_rate_failed:
+ {
+ GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
+ ("DSP_SPEED(%d) failed: %s", rate, g_strerror (errno)));
+ return FALSE;
+ }
+get_ospace_failed:
+ {
+ GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
+ ("DSP_GETOSPACE failed: %s", g_strerror (errno)));
+ return FALSE;
+ }
+get_ispace_failed:
+ {
+ GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
+ ("DSP_GETISPACE failed: %s", g_strerror (errno)));
+ return FALSE;
+ }
+format_not_what_was_requested:
+ {
+ GST_ELEMENT_ERROR (obj, RESOURCE, SETTINGS, (NULL),
+ ("Format actually configured wasn't the one we requested. This is "
+ "probably either a bug in the driver or in the format probing code."));
+ return FALSE;
+ }
+}
+
+int
+gst_oss4_audio_get_version (GstObject * obj, int fd)
+{
+ gint ver = 0;
+
+ /* we use the old ioctl here on purpose instead of SNDCTL_SYSINFO */
+ if (ioctl (fd, OSS_GETVERSION, &ver) < 0) {
+ GST_LOG_OBJECT (obj, "OSS_GETVERSION failed: %s", g_strerror (errno));
+ return -1;
+ }
+ GST_LOG_OBJECT (obj, "OSS version: 0x%08x", ver);
+ return ver;
+}
+
+gboolean
+gst_oss4_audio_check_version (GstObject * obj, int fd)
+{
+ return (gst_oss4_audio_get_version (obj, fd) >= GST_MIN_OSS4_VERSION);
+}
+
+gchar *
+gst_oss4_audio_find_device (GstObject * oss)
+{
+ GValueArray *arr;
+ gchar *ret = NULL;
+
+ arr = gst_property_probe_probe_and_get_values_name (GST_PROPERTY_PROBE (oss),
+ "device");
+
+ if (arr != NULL) {
+ if (arr->n_values > 0) {
+ const GValue *val;
+
+ val = g_value_array_get_nth (arr, 0);
+ ret = g_value_dup_string (val);
+ }
+ g_value_array_free (arr);
+ }
+
+ GST_LOG_OBJECT (oss, "first device found: %s", GST_STR_NULL (ret));
+
+ return ret;
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ gint rank;
+
+ GST_DEBUG_CATEGORY_INIT (oss4sink_debug, "oss4sink", 0, "OSS4 audio sink");
+ GST_DEBUG_CATEGORY_INIT (oss4src_debug, "oss4src", 0, "OSS4 audio src");
+ GST_DEBUG_CATEGORY_INIT (oss4mixer_debug, "oss4mixer", 0, "OSS4 mixer");
+ GST_DEBUG_CATEGORY_INIT (oss4_debug, "oss4", 0, "OSS4 plugin");
+
+#ifdef ENABLE_NLS
+ GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
+ LOCALEDIR);
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+#endif
+
+ /* we want a higher rank than the legacy OSS elements have now */
+ rank = GST_RANK_SECONDARY + 1;
+
+ if (!gst_element_register (plugin, "oss4sink", rank, GST_TYPE_OSS4_SINK) ||
+ !gst_element_register (plugin, "oss4src", rank, GST_TYPE_OSS4_SOURCE) ||
+ !gst_element_register (plugin, "oss4mixer", rank, GST_TYPE_OSS4_MIXER)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "oss4",
+ "Open Sound System (OSS) version 4 support for GStreamer",
+ plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/oss4/oss4-audio.h b/sys/oss4/oss4-audio.h
new file mode 100644
index 0000000..d220364
--- /dev/null
+++ b/sys/oss4/oss4-audio.h
@@ -0,0 +1,43 @@
+/* GStreamer OSS4 audio plugin
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+
+#ifndef GST_OSS4_AUDIO_H
+#define GST_OSS4_AUDIO_H_
+
+#include <gst/gst.h>
+#include <gst/audio/gstringbuffer.h>
+
+/* This is the minimum version we require */
+#define GST_MIN_OSS4_VERSION 0x040003
+
+int gst_oss4_audio_get_version (GstObject * obj, int fd);
+
+gboolean gst_oss4_audio_check_version (GstObject * obj, int fd);
+
+GstCaps * gst_oss4_audio_probe_caps (GstObject * obj, int fd);
+
+gboolean gst_oss4_audio_set_format (GstObject * obj, int fd, GstRingBufferSpec * spec);
+
+GstCaps * gst_oss4_audio_get_template_caps (void);
+
+gchar * gst_oss4_audio_find_device (GstObject * oss);
+
+#endif /* GST_OSS4_AUDIO_H */
+
+
diff --git a/sys/oss4/oss4-mixer-enum.c b/sys/oss4/oss4-mixer-enum.c
new file mode 100644
index 0000000..4b64bb1
--- /dev/null
+++ b/sys/oss4/oss4-mixer-enum.c
@@ -0,0 +1,269 @@
+/* GStreamer OSS4 mixer enumeration control
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+
+/* An 'enum' in gnome-volume-control / GstMixer is represented by a
+ * GstMixerOptions object
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst-i18n-plugin.h>
+
+#define NO_LEGACY_MIXER
+#include "oss4-mixer.h"
+#include "oss4-mixer-enum.h"
+#include "oss4-soundcard.h"
+
+GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug);
+#define GST_CAT_DEFAULT oss4mixer_debug
+
+static GList *gst_oss4_mixer_enum_get_values (GstMixerOptions * options);
+
+/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */
+G_DEFINE_TYPE (GstOss4MixerEnum, gst_oss4_mixer_enum, GST_TYPE_MIXER_OPTIONS);
+
+static void
+gst_oss4_mixer_enum_init (GstOss4MixerEnum * e)
+{
+ e->need_update = TRUE;
+}
+
+static void
+gst_oss4_mixer_enum_dispose (GObject * obj)
+{
+ GstMixerOptions *options = GST_MIXER_OPTIONS (obj);
+
+ /* our list is a flat list with constant strings, but the GstMixerOptions
+ * dispose will try to g_free the contained strings, so clean up the list
+ * before chaining up to GstMixerOptions */
+ g_list_free (options->values);
+ options->values = NULL;
+
+ G_OBJECT_CLASS (gst_oss4_mixer_enum_parent_class)->dispose (obj);
+}
+
+static void
+gst_oss4_mixer_enum_class_init (GstOss4MixerEnumClass * klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstMixerOptionsClass *mixeroptions_class = (GstMixerOptionsClass *) klass;
+
+ gobject_class->dispose = gst_oss4_mixer_enum_dispose;
+ mixeroptions_class->get_values = gst_oss4_mixer_enum_get_values;
+}
+
+static GList *
+gst_oss4_mixer_enum_get_values_locked (GstMixerOptions * options)
+{
+ GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM_CAST (options);
+ GList *oldlist, *list = NULL;
+ int i;
+
+ /* if current list of values is empty, update/re-check in any case */
+ if (!e->need_update && options->values != NULL)
+ return options->values;
+
+ GST_LOG_OBJECT (e, "updating available values for %s", e->mc->mixext.extname);
+
+ for (i = 0; i < e->mc->mixext.maxvalue; ++i) {
+ const gchar *s;
+
+ s = g_quark_to_string (e->mc->enum_vals[i]);
+ if (MIXEXT_ENUM_IS_AVAILABLE (e->mc->mixext, i)) {
+ GST_LOG_OBJECT (e, "option '%s' is available", s);
+ list = g_list_prepend (list, (gpointer) s);
+ } else {
+ GST_LOG_OBJECT (e, "option '%s' is currently not available", s);
+ }
+ }
+
+ list = g_list_reverse (list);
+
+ /* this is not thread-safe, but then the entire GstMixer API isn't really,
+ * since we return foo->list and not a copy and don't take any locks, so
+ * not much we can do here but pray; we're usually either called from _new()
+ * or from within _get_values() though, so it should be okay. We could use
+ * atomic ops here, but I'm not sure how much more that really buys us.*/
+ oldlist = options->values; /* keep window small */
+ options->values = list;
+ g_list_free (oldlist);
+
+ e->need_update = FALSE;
+
+ return options->values;
+}
+
+static GList *
+gst_oss4_mixer_enum_get_values (GstMixerOptions * options)
+{
+ GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM (options);
+ GList *list;
+
+ /* we take the lock here mostly to serialise ioctls with the watch thread */
+ GST_OBJECT_LOCK (e->mixer);
+
+ list = gst_oss4_mixer_enum_get_values_locked (options);
+
+ GST_OBJECT_UNLOCK (e->mixer);
+
+ return list;
+}
+
+static const gchar *
+gst_oss4_mixer_enum_get_current_value (GstOss4MixerEnum * e)
+{
+ const gchar *cur_val = NULL;
+
+ if (e->mc->enum_vals != NULL && e->mc->last_val < e->mc->mixext.maxvalue) {
+ cur_val = g_quark_to_string (e->mc->enum_vals[e->mc->last_val]);
+ }
+
+ return cur_val;
+}
+
+static gboolean
+gst_oss4_mixer_enum_update_current (GstOss4MixerEnum * e)
+{
+ int cur = -1;
+
+ if (!gst_oss4_mixer_get_control_val (e->mixer, e->mc, &cur))
+ return FALSE;
+
+ if (cur < 0 || cur >= e->mc->mixext.maxvalue) {
+ GST_WARNING_OBJECT (e, "read value %d out of bounds [0-%d]", cur,
+ e->mc->mixext.maxvalue - 1);
+ e->mc->last_val = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+gst_oss4_mixer_enum_set_option (GstOss4MixerEnum * e, const gchar * value)
+{
+ GQuark q;
+ int i;
+
+ q = g_quark_try_string (value);
+ if (q == 0) {
+ GST_WARNING_OBJECT (e, "unknown option '%s'", value);
+ return FALSE;
+ }
+
+ for (i = 0; i < e->mc->mixext.maxvalue; ++i) {
+ if (q == e->mc->enum_vals[i])
+ break;
+ }
+
+ if (i >= e->mc->mixext.maxvalue) {
+ GST_WARNING_OBJECT (e, "option '%s' is not valid for this control", value);
+ return FALSE;
+ }
+
+ GST_LOG_OBJECT (e, "option '%s' = %d", value, i);
+
+ if (!MIXEXT_ENUM_IS_AVAILABLE (e->mc->mixext, i)) {
+ GST_WARNING_OBJECT (e, "option '%s' is not selectable currently", value);
+ return FALSE;
+ }
+
+ if (!gst_oss4_mixer_set_control_val (e->mixer, e->mc, i)) {
+ GST_WARNING_OBJECT (e, "could not set option '%s' (%d)", value, i);
+ return FALSE;
+ }
+
+ /* and re-read current value with sanity checks (or could just assign here) */
+ gst_oss4_mixer_enum_update_current (e);
+
+ return TRUE;
+}
+
+const gchar *
+gst_oss4_mixer_enum_get_option (GstOss4MixerEnum * e)
+{
+ const gchar *cur_str = NULL;
+
+ if (!gst_oss4_mixer_enum_update_current (e)) {
+ GST_WARNING_OBJECT (e, "failed to read current value");
+ return NULL;
+ }
+
+ cur_str = gst_oss4_mixer_enum_get_current_value (e);
+ GST_LOG_OBJECT (e, "%s (%d)", GST_STR_NULL (cur_str), e->mc->last_val);
+ return cur_str;
+}
+
+GstMixerTrack *
+gst_oss4_mixer_enum_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc)
+{
+ GstOss4MixerEnum *e;
+ GstMixerTrack *track;
+
+ e = g_object_new (GST_TYPE_OSS4_MIXER_ENUM, "untranslated-label",
+ mc->mixext.extname, NULL);
+ e->mixer = mixer;
+ e->mc = mc;
+
+ track = GST_MIXER_TRACK (e);
+
+ /* caller will set track->label and track->flags */
+
+ track->num_channels = 0;
+ track->min_volume = 0;
+ track->max_volume = 0;
+
+ (void) gst_oss4_mixer_enum_get_values_locked (GST_MIXER_OPTIONS (track));
+
+ if (!gst_oss4_mixer_enum_update_current (e)) {
+ GST_WARNING_OBJECT (track, "failed to read current value, returning NULL");
+ g_object_unref (track);
+ track = NULL;
+ }
+
+ GST_LOG_OBJECT (e, "current value: %d (%s)", e->mc->last_val,
+ gst_oss4_mixer_enum_get_current_value (e));
+
+ return track;
+}
+
+/* This is called from the watch thread */
+void
+gst_oss4_mixer_enum_process_change_unlocked (GstMixerTrack * track)
+{
+ GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM_CAST (track);
+
+ gchar *cur;
+
+ if (!e->mc->changed && !e->mc->list_changed)
+ return;
+
+ if (e->mc->list_changed) {
+ gst_mixer_options_list_changed (GST_MIXER (e->mixer),
+ GST_MIXER_OPTIONS (e));
+ }
+
+ GST_OBJECT_LOCK (e->mixer);
+ cur = (gchar *) gst_oss4_mixer_enum_get_current_value (e);
+ GST_OBJECT_UNLOCK (e->mixer);
+
+ gst_mixer_option_changed (GST_MIXER (e->mixer), GST_MIXER_OPTIONS (e), cur);
+}
diff --git a/sys/oss4/oss4-mixer-enum.h b/sys/oss4/oss4-mixer-enum.h
new file mode 100644
index 0000000..9fd8166
--- /dev/null
+++ b/sys/oss4/oss4-mixer-enum.h
@@ -0,0 +1,67 @@
+/* GStreamer OSS4 mixer on/off enum control
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+
+#ifndef GST_OSS4_MIXER_ENUM_H
+#define GST_OSS4_MIXER_ENUM_H
+
+#include <gst/gst.h>
+#include <gst/interfaces/mixer.h>
+
+#include "oss4-mixer.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSS4_MIXER_ENUM (gst_oss4_mixer_enum_get_type())
+#define GST_OSS4_MIXER_ENUM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_MIXER_ENUM,GstOss4MixerEnum))
+#define GST_OSS4_MIXER_ENUM_CAST(obj) ((GstOss4MixerEnum *)(obj))
+#define GST_OSS4_MIXER_ENUM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_MIXER_ENUM,GstOss4MixerEnumClass))
+#define GST_IS_OSS4_MIXER_ENUM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_MIXER_ENUM))
+#define GST_IS_OSS4_MIXER_ENUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_MIXER_ENUM))
+
+typedef struct _GstOss4MixerEnum GstOss4MixerEnum;
+typedef struct _GstOss4MixerEnumClass GstOss4MixerEnumClass;
+
+struct _GstOss4MixerEnum {
+ GstMixerOptions mixer_option;
+
+ GstOss4MixerControl * mc;
+ GstOss4Mixer * mixer; /* the mixer we belong to (no ref taken) */
+
+ gboolean need_update;
+};
+
+struct _GstOss4MixerEnumClass {
+ GstMixerOptionsClass mixer_option_class;
+};
+
+GType gst_oss4_mixer_enum_get_type (void);
+
+gboolean gst_oss4_mixer_enum_set_option (GstOss4MixerEnum * e, const gchar * value);
+
+const gchar * gst_oss4_mixer_enum_get_option (GstOss4MixerEnum * e);
+
+GstMixerTrack * gst_oss4_mixer_enum_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc);
+
+void gst_oss4_mixer_enum_process_change_unlocked (GstMixerTrack * track);
+
+G_END_DECLS
+
+#endif /* GST_OSS4_MIXER_ENUM_H */
+
+
diff --git a/sys/oss4/oss4-mixer-slider.c b/sys/oss4/oss4-mixer-slider.c
new file mode 100644
index 0000000..ea2bc8c
--- /dev/null
+++ b/sys/oss4/oss4-mixer-slider.c
@@ -0,0 +1,311 @@
+/* GStreamer OSS4 mixer slider control
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+
+/* A 'slider' in gnome-volume-control / GstMixer is represented by a
+ * GstMixerTrack with one or more channels.
+ *
+ * A slider should be either flagged as INPUT or OUTPUT (mostly because of
+ * gnome-volume-control being littered with g_asserts for everything it doesn't
+ * expect).
+ *
+ * From mixertrack.h:
+ * "Input tracks can have 'recording' enabled, which means that any input will
+ * be hearable into the speakers that are attached to the output. Mute is
+ * obvious."
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#include <gst/gst-i18n-plugin.h>
+
+#define NO_LEGACY_MIXER
+#include "oss4-mixer-slider.h"
+
+GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug);
+#define GST_CAT_DEFAULT oss4mixer_debug
+
+/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */
+G_DEFINE_TYPE (GstOss4MixerSlider, gst_oss4_mixer_slider, GST_TYPE_MIXER_TRACK);
+
+static void
+gst_oss4_mixer_slider_class_init (GstOss4MixerSliderClass * klass)
+{
+ /* nothing to do here */
+}
+
+static void
+gst_oss4_mixer_slider_init (GstOss4MixerSlider * s)
+{
+ /* nothing to do here */
+}
+
+static int
+gst_oss4_mixer_slider_pack_volume (GstOss4MixerSlider * s, const gint * volumes)
+{
+ int val = 0;
+
+ switch (s->mc->mixext.type) {
+ case MIXT_MONOSLIDER:
+ case MIXT_MONOSLIDER16:
+ case MIXT_SLIDER:
+ val = volumes[0];
+ break;
+ case MIXT_STEREOSLIDER:
+ val = ((volumes[1] & 0xff) << 8) | (volumes[0] & 0xff);
+ break;
+ case MIXT_STEREOSLIDER16:
+ val = ((volumes[1] & 0xffff) << 16) | (volumes[0] & 0xffff);
+ break;
+ default:
+ g_return_val_if_reached (0);
+ }
+ return val;
+}
+
+static void
+gst_oss4_mixer_slider_unpack_volume (GstOss4MixerSlider * s, int v,
+ gint * volumes)
+{
+ guint32 val; /* use uint so bitshifting the highest bit works right */
+
+ val = (guint32) v;
+ switch (s->mc->mixext.type) {
+ case MIXT_SLIDER:
+ volumes[0] = val;
+ break;
+ case MIXT_MONOSLIDER:
+ /* oss repeats the value in the upper bits, as if it was stereo */
+ volumes[0] = val & 0x00ff;
+ break;
+ case MIXT_MONOSLIDER16:
+ /* oss repeats the value in the upper bits, as if it was stereo */
+ volumes[0] = val & 0x0000ffff;
+ break;
+ case MIXT_STEREOSLIDER:
+ volumes[0] = (val & 0x00ff);
+ volumes[1] = (val & 0xff00) >> 8;
+ break;
+ case MIXT_STEREOSLIDER16:
+ volumes[0] = (val & 0x0000ffff);
+ volumes[1] = (val & 0xffff0000) >> 16;
+ break;
+ default:
+ g_return_if_reached ();
+ }
+}
+
+gboolean
+gst_oss4_mixer_slider_get_volume (GstOss4MixerSlider * s, gint * volumes)
+{
+ GstMixerTrack *track = GST_MIXER_TRACK (s);
+ int v = 0;
+
+ /* if we're supposed to be muted, and don't have an actual mute control
+ * (ie. 'simulate' the mute), then just return the volume as saved, not
+ * the actually set volume which is most likely 0 */
+ if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE) && !s->mc->mute) {
+ volumes[0] = s->volumes[0];
+ if (track->num_channels == 2)
+ volumes[1] = s->volumes[1];
+ return TRUE;
+ }
+
+ if (!gst_oss4_mixer_get_control_val (s->mixer, s->mc, &v))
+ return FALSE;
+
+ gst_oss4_mixer_slider_unpack_volume (s, v, volumes);
+
+ if (track->num_channels > 1) {
+ GST_LOG_OBJECT (s, "volume: left=%d, right=%d", volumes[0], volumes[1]);
+ } else {
+ GST_LOG_OBJECT (s, "volume: mono=%d", volumes[0]);
+ }
+
+ return TRUE;
+}
+
+gboolean
+gst_oss4_mixer_slider_set_volume (GstOss4MixerSlider * s, const gint * volumes)
+{
+ GstMixerTrack *track = GST_MIXER_TRACK (s);
+ int val = 0;
+
+ /* if we're supposed to be muted, and are 'simulating' the mute because
+ * we don't have a mute control, don't actually change the volume, just
+ * save it as the new desired volume for later when we get unmuted again */
+ if (!GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_NO_MUTE)) {
+ if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE) && !s->mc->mute)
+ goto done;
+ }
+
+ val = gst_oss4_mixer_slider_pack_volume (s, volumes);
+
+ if (track->num_channels > 1) {
+ GST_LOG_OBJECT (s, "left=%d, right=%d", volumes[0], volumes[1]);
+ } else {
+ GST_LOG_OBJECT (s, "mono=%d", volumes[0]);
+ }
+
+ if (!gst_oss4_mixer_set_control_val (s->mixer, s->mc, val))
+ return FALSE;
+
+done:
+
+ s->volumes[0] = volumes[0];
+ if (track->num_channels == 2)
+ s->volumes[1] = volumes[1];
+
+ return TRUE;
+}
+
+gboolean
+gst_oss4_mixer_slider_set_record (GstOss4MixerSlider * s, gboolean record)
+{
+ /* There doesn't seem to be a way to do this using the OSS4 mixer API, so
+ * just do nothing here for now. */
+ return FALSE;
+}
+
+gboolean
+gst_oss4_mixer_slider_set_mute (GstOss4MixerSlider * s, gboolean mute)
+{
+ GstMixerTrack *track = GST_MIXER_TRACK (s);
+ gboolean ret;
+
+ /* if the control does not support muting, then do not do anything */
+ if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_NO_MUTE)) {
+ return TRUE;
+ }
+
+ /* If we do not have a mute control, simulate mute (which is a bit broken,
+ * since we can not differentiate between capture/playback volume etc., so
+ * we just assume that setting the volume to 0 would be the same as muting
+ * this control) */
+ if (s->mc->mute == NULL) {
+ int volume;
+
+ if (mute) {
+ /* make sure the current volume values get saved. */
+ gst_oss4_mixer_slider_get_volume (s, s->volumes);
+ volume = 0;
+ } else {
+ volume = gst_oss4_mixer_slider_pack_volume (s, s->volumes);
+ }
+ ret = gst_oss4_mixer_set_control_val (s->mixer, s->mc, volume);
+ } else {
+ ret = gst_oss4_mixer_set_control_val (s->mixer, s->mc->mute, ! !mute);
+ }
+
+ if (mute) {
+ track->flags |= GST_MIXER_TRACK_MUTE;
+ } else {
+ track->flags &= ~GST_MIXER_TRACK_MUTE;
+ }
+
+ return ret;
+}
+
+GstMixerTrack *
+gst_oss4_mixer_slider_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc)
+{
+ GstOss4MixerSlider *s;
+ GstMixerTrack *track;
+ gint volumes[2] = { 0, };
+
+ s = g_object_new (GST_TYPE_OSS4_MIXER_SLIDER, "untranslated-label",
+ mc->mixext.extname, NULL);
+
+ track = GST_MIXER_TRACK (s);
+
+ /* caller will set track->label and track->flags */
+
+ s->mc = mc;
+ s->mixer = mixer;
+
+ /* we don't do value scaling but just present a scale of 0-maxvalue */
+ track->min_volume = 0;
+ track->max_volume = mc->mixext.maxvalue;
+
+ switch (mc->mixext.type) {
+ case MIXT_MONOSLIDER:
+ case MIXT_MONOSLIDER16:
+ case MIXT_SLIDER:
+ track->num_channels = 1;
+ break;
+ case MIXT_STEREOSLIDER:
+ case MIXT_STEREOSLIDER16:
+ track->num_channels = 2;
+ break;
+ default:
+ g_return_val_if_reached (NULL);
+ }
+
+ GST_LOG_OBJECT (track, "min=%d, max=%d, channels=%d", track->min_volume,
+ track->max_volume, track->num_channels);
+
+ if (!gst_oss4_mixer_slider_get_volume (s, volumes)) {
+ GST_WARNING_OBJECT (track, "failed to read volume, returning NULL");
+ g_object_unref (track);
+ track = NULL;
+ }
+
+ return track;
+}
+
+/* This is called from the watch thread */
+void
+gst_oss4_mixer_slider_process_change_unlocked (GstMixerTrack * track)
+{
+ GstOss4MixerSlider *s = GST_OSS4_MIXER_SLIDER_CAST (track);
+
+ if (s->mc->mute != NULL && s->mc->mute->changed) {
+ gst_mixer_mute_toggled (GST_MIXER (s->mixer), track,
+ ! !s->mc->mute->last_val);
+ } else {
+ /* nothing to do here, since we don't/can't easily implement the record
+ * flag */
+ }
+
+ if (s->mc->changed) {
+ gint volumes[2] = { 0, 0 };
+
+ gst_oss4_mixer_slider_unpack_volume (s, s->mc->last_val, volumes);
+
+ /* if we 'simulate' the mute, update flag when the volume changes */
+ if (s->mc->mute == NULL) {
+ if (volumes[0] == 0 && volumes[1] == 0) {
+ track->flags |= GST_MIXER_TRACK_MUTE;
+ } else {
+ track->flags &= ~GST_MIXER_TRACK_MUTE;
+ }
+ }
+
+ gst_mixer_volume_changed (GST_MIXER (s->mixer), track, volumes);
+ }
+}
diff --git a/sys/oss4/oss4-mixer-slider.h b/sys/oss4/oss4-mixer-slider.h
new file mode 100644
index 0000000..3bee33f
--- /dev/null
+++ b/sys/oss4/oss4-mixer-slider.h
@@ -0,0 +1,70 @@
+/* GStreamer OSS4 mixer slider control
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+
+#ifndef GST_OSS4_MIXER_SLIDER_H
+#define GST_OSS4_MIXER_SLIDER_H
+
+#include <gst/gst.h>
+#include <gst/interfaces/mixer.h>
+
+#include "oss4-mixer.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSS4_MIXER_SLIDER (gst_oss4_mixer_slider_get_type())
+#define GST_OSS4_MIXER_SLIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_MIXER_SLIDER,GstOss4MixerSlider))
+#define GST_OSS4_MIXER_SLIDER_CAST(obj) ((GstOss4MixerSlider *)(obj))
+#define GST_OSS4_MIXER_SLIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_MIXER_SLIDER,GstOss4MixerSliderClass))
+#define GST_IS_OSS4_MIXER_SLIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_MIXER_SLIDER))
+#define GST_IS_OSS4_MIXER_SLIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_MIXER_SLIDER))
+
+typedef struct _GstOss4MixerSlider GstOss4MixerSlider;
+typedef struct _GstOss4MixerSliderClass GstOss4MixerSliderClass;
+
+struct _GstOss4MixerSlider {
+ GstMixerTrack mixer_track;
+
+ GstOss4MixerControl * mc;
+ GstOss4Mixer * mixer; /* the mixer we belong to (no ref taken) */
+ gint volumes[2]; /* left/mono, right */
+};
+
+struct _GstOss4MixerSliderClass {
+ GstMixerTrackClass mixer_track_class;
+};
+
+GType gst_oss4_mixer_slider_get_type (void);
+
+GstMixerTrack * gst_oss4_mixer_slider_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc);
+
+gboolean gst_oss4_mixer_slider_get_volume (GstOss4MixerSlider * s, gint * volumes);
+
+gboolean gst_oss4_mixer_slider_set_volume (GstOss4MixerSlider * s, const gint * volumes);
+
+gboolean gst_oss4_mixer_slider_set_record (GstOss4MixerSlider * s, gboolean record);
+
+gboolean gst_oss4_mixer_slider_set_mute (GstOss4MixerSlider * s, gboolean mute);
+
+void gst_oss4_mixer_slider_process_change_unlocked (GstMixerTrack * track);
+
+G_END_DECLS
+
+#endif /* GST_OSS4_MIXER_SLIDER_H */
+
+
diff --git a/sys/oss4/oss4-mixer-switch.c b/sys/oss4/oss4-mixer-switch.c
new file mode 100644
index 0000000..0a6ce5b
--- /dev/null
+++ b/sys/oss4/oss4-mixer-switch.c
@@ -0,0 +1,150 @@
+/* GStreamer OSS4 mixer on/off switch control
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+
+/* A simple ON/OFF 'switch' in gnome-volume-control / GstMixer is represented
+ * by a GstMixerTrack with no channels.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst-i18n-plugin.h>
+
+#define NO_LEGACY_MIXER
+#include "oss4-mixer-switch.h"
+#include "oss4-soundcard.h"
+
+GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug);
+#define GST_CAT_DEFAULT oss4mixer_debug
+
+/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */
+G_DEFINE_TYPE (GstOss4MixerSwitch, gst_oss4_mixer_switch, GST_TYPE_MIXER_TRACK);
+
+static void
+gst_oss4_mixer_switch_class_init (GstOss4MixerSwitchClass * klass)
+{
+ /* nothing to do here */
+}
+
+static void
+gst_oss4_mixer_switch_init (GstOss4MixerSwitch * s)
+{
+ /* nothing to do here */
+}
+
+gboolean
+gst_oss4_mixer_switch_set (GstOss4MixerSwitch * s, gboolean disabled)
+{
+ GstMixerTrack *track;
+ int newval;
+
+ track = GST_MIXER_TRACK (s);
+
+ newval = disabled ? GST_MIXER_TRACK_MUTE : 0;
+
+ if (newval == (track->flags & GST_MIXER_TRACK_MUTE)) {
+ GST_LOG_OBJECT (s, "switch is already %d, doing nothing", newval);
+ return TRUE;
+ }
+
+ if (!gst_oss4_mixer_set_control_val (s->mixer, s->mc, !disabled)) {
+ GST_WARNING_OBJECT (s, "could not set switch to %d", !disabled);
+ return FALSE;
+ }
+
+ if (disabled) {
+ track->flags |= GST_MIXER_TRACK_MUTE;
+ } else {
+ track->flags &= ~GST_MIXER_TRACK_MUTE;
+ }
+
+ GST_LOG_OBJECT (s, "set switch to %d", newval);
+
+ return TRUE;
+}
+
+gboolean
+gst_oss4_mixer_switch_get (GstOss4MixerSwitch * s, gboolean * disabled)
+{
+ GstMixerTrack *track;
+ int enabled = -1;
+
+ track = GST_MIXER_TRACK (s);
+
+ if (!gst_oss4_mixer_get_control_val (s->mixer, s->mc, &enabled)
+ || (enabled < 0)) {
+ GST_WARNING_OBJECT (s, "could not get switch state");
+ return FALSE;
+ }
+
+ if (enabled) {
+ track->flags &= ~GST_MIXER_TRACK_MUTE;
+ } else {
+ track->flags |= GST_MIXER_TRACK_MUTE;
+ }
+ *disabled = (enabled == 0);
+
+ return TRUE;
+}
+
+GstMixerTrack *
+gst_oss4_mixer_switch_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc)
+{
+ GstOss4MixerSwitch *s;
+ GstMixerTrack *track;
+ int cur = -1;
+
+ s = g_object_new (GST_TYPE_OSS4_MIXER_SWITCH, "untranslated-label",
+ mc->mixext.extname, NULL);
+
+ s->mixer = mixer;
+ s->mc = mc;
+
+ track = GST_MIXER_TRACK (s);
+
+ /* caller will set track->label and track->flags */
+
+ track->num_channels = 0;
+ track->min_volume = 0;
+ track->max_volume = 0;
+
+ if (!gst_oss4_mixer_get_control_val (s->mixer, s->mc, &cur) || cur < 0)
+ return NULL;
+
+ if (cur) {
+ track->flags &= ~GST_MIXER_TRACK_MUTE;
+ } else {
+ track->flags |= GST_MIXER_TRACK_MUTE;
+ }
+
+ return track;
+}
+
+/* This is called from the watch thread */
+void
+gst_oss4_mixer_switch_process_change_unlocked (GstMixerTrack * track)
+{
+ GstOss4MixerSwitch *s = GST_OSS4_MIXER_SWITCH_CAST (track);
+
+ if (!s->mc->changed)
+ return;
+
+ gst_mixer_mute_toggled (GST_MIXER (s->mixer), track, !s->mc->last_val);
+}
diff --git a/sys/oss4/oss4-mixer-switch.h b/sys/oss4/oss4-mixer-switch.h
new file mode 100644
index 0000000..a8ab83f
--- /dev/null
+++ b/sys/oss4/oss4-mixer-switch.h
@@ -0,0 +1,65 @@
+/* GStreamer OSS4 mixer on/off switch control
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+
+#ifndef GST_OSS4_MIXER_SWITCH_H
+#define GST_OSS4_MIXER_SWITCH_H
+
+#include <gst/gst.h>
+#include <gst/interfaces/mixer.h>
+
+#include "oss4-mixer.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSS4_MIXER_SWITCH (gst_oss4_mixer_switch_get_type())
+#define GST_OSS4_MIXER_SWITCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_MIXER_SWITCH,GstOss4MixerSwitch))
+#define GST_OSS4_MIXER_SWITCH_CAST(obj) ((GstOss4MixerSwitch *)(obj))
+#define GST_OSS4_MIXER_SWITCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_MIXER_SWITCH,GstOss4MixerSwitchClass))
+#define GST_IS_OSS4_MIXER_SWITCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_MIXER_SWITCH))
+#define GST_IS_OSS4_MIXER_SWITCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_MIXER_SWITCH))
+
+typedef struct _GstOss4MixerSwitch GstOss4MixerSwitch;
+typedef struct _GstOss4MixerSwitchClass GstOss4MixerSwitchClass;
+
+struct _GstOss4MixerSwitch {
+ GstMixerTrack mixer_track;
+
+ GstOss4MixerControl * mc;
+ GstOss4Mixer * mixer; /* the mixer we belong to (no ref taken) */
+};
+
+struct _GstOss4MixerSwitchClass {
+ GstMixerTrackClass mixer_track_class;
+};
+
+GType gst_oss4_mixer_switch_get_type (void);
+
+gboolean gst_oss4_mixer_switch_set (GstOss4MixerSwitch * s, gboolean enabled);
+
+gboolean gst_oss4_mixer_switch_get (GstOss4MixerSwitch * s, gboolean * enabled);
+
+GstMixerTrack * gst_oss4_mixer_switch_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc);
+
+void gst_oss4_mixer_switch_process_change_unlocked (GstMixerTrack * track);
+
+G_END_DECLS
+
+#endif /* GST_OSS4_MIXER_SWITCH_H */
+
+
diff --git a/sys/oss4/oss4-mixer.c b/sys/oss4/oss4-mixer.c
new file mode 100644
index 0000000..03e2d9d
--- /dev/null
+++ b/sys/oss4/oss4-mixer.c
@@ -0,0 +1,1862 @@
+/* GStreamer OSS4 mixer implementation
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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 mixer library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:element-oss4mixer
+ *
+ * This element lets you adjust sound input and output levels with the
+ * Open Sound System (OSS) version 4. It supports the GstMixer interface, which
+ * can be used to obtain a list of available mixer tracks. Set the mixer
+ * element to READY state before using the GstMixer interface on it.
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * <para>
+ * oss4mixer can&apos;t be used in a sensible way in gst-launch.
+ * </para>
+ * </refsect2>
+ *
+ * Since: 0.10.7
+ */
+
+/* Note: ioctl calls on the same open mixer device are serialised via
+ * the object lock to make sure we don't do concurrent ioctls from two
+ * different threads (e.g. app thread and mixer watch thread), since that
+ * will probably confuse OSS. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#include <gst/interfaces/mixer.h>
+#include <gst/gst-i18n-plugin.h>
+#include "gst/glib-compat-private.h"
+
+#include <glib/gprintf.h>
+
+#define NO_LEGACY_MIXER
+
+#include "oss4-audio.h"
+#include "oss4-mixer.h"
+#include "oss4-mixer-enum.h"
+#include "oss4-mixer-slider.h"
+#include "oss4-mixer-switch.h"
+#include "oss4-property-probe.h"
+#include "oss4-soundcard.h"
+
+#define GST_OSS4_MIXER_WATCH_INTERVAL 500 /* in millisecs, ie. 0.5s */
+
+GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug);
+#define GST_CAT_DEFAULT oss4mixer_debug
+
+#define DEFAULT_DEVICE NULL
+#define DEFAULT_DEVICE_NAME NULL
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+ PROP_DEVICE_NAME
+};
+
+static void gst_oss4_mixer_init_interfaces (GType type);
+
+GST_BOILERPLATE_FULL (GstOss4Mixer, gst_oss4_mixer, GstElement,
+ GST_TYPE_ELEMENT, gst_oss4_mixer_init_interfaces);
+
+static GstStateChangeReturn gst_oss4_mixer_change_state (GstElement *
+ element, GstStateChange transition);
+
+static void gst_oss4_mixer_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_oss4_mixer_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static void gst_oss4_mixer_finalize (GObject * object);
+
+static gboolean gst_oss4_mixer_open (GstOss4Mixer * mixer,
+ gboolean silent_errors);
+static void gst_oss4_mixer_close (GstOss4Mixer * mixer);
+
+static gboolean gst_oss4_mixer_enum_control_update_enum_list (GstOss4Mixer * m,
+ GstOss4MixerControl * mc);
+
+#ifndef GST_DISABLE_GST_DEBUG
+static const gchar *mixer_ext_type_get_name (gint type);
+static const gchar *mixer_ext_flags_get_string (gint flags);
+#endif
+
+static void
+gst_oss4_mixer_base_init (gpointer klass)
+{
+ gst_element_class_set_details_simple (GST_ELEMENT_CLASS (klass),
+ "OSS v4 Audio Mixer", "Generic/Audio",
+ "Control sound input and output levels with OSS4",
+ "Tim-Philipp Müller <tim centricular net>");
+}
+
+static void
+gst_oss4_mixer_class_init (GstOss4MixerClass * klass)
+{
+ GstElementClass *element_class;
+ GObjectClass *gobject_class;
+
+ element_class = (GstElementClass *) klass;
+ gobject_class = (GObjectClass *) klass;
+
+ gobject_class->finalize = gst_oss4_mixer_finalize;
+ gobject_class->set_property = gst_oss4_mixer_set_property;
+ gobject_class->get_property = gst_oss4_mixer_get_property;
+
+ /**
+ * GstOss4Mixer:device
+ *
+ * OSS4 mixer device (e.g. /dev/oss/hdaudio0/mix0 or /dev/mixerN)
+ *
+ **/
+ g_object_class_install_property (gobject_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device",
+ "OSS mixer device (e.g. /dev/oss/hdaudio0/mix0 or /dev/mixerN) "
+ "(NULL = use first mixer device found)", DEFAULT_DEVICE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GstOss4Mixer:device-name
+ *
+ * Human-readable name of the sound device. May be NULL if the device is
+ * not open (ie. when the mixer is in NULL state)
+ *
+ **/
+ g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
+ g_param_spec_string ("device-name", "Device name",
+ "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ element_class->change_state = GST_DEBUG_FUNCPTR (gst_oss4_mixer_change_state);
+}
+
+static void
+gst_oss4_mixer_finalize (GObject * obj)
+{
+ GstOss4Mixer *mixer = GST_OSS4_MIXER (obj);
+
+ g_free (mixer->device);
+
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+static void
+gst_oss4_mixer_reset (GstOss4Mixer * mixer)
+{
+ mixer->fd = -1;
+ mixer->need_update = TRUE;
+ memset (&mixer->last_mixext, 0, sizeof (oss_mixext));
+}
+
+static void
+gst_oss4_mixer_init (GstOss4Mixer * mixer, GstOss4MixerClass * g_class)
+{
+ mixer->device = g_strdup (DEFAULT_DEVICE);
+ mixer->device_name = NULL;
+
+ gst_oss4_mixer_reset (mixer);
+}
+
+static void
+gst_oss4_mixer_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOss4Mixer *mixer = GST_OSS4_MIXER (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ GST_OBJECT_LOCK (mixer);
+ if (!GST_OSS4_MIXER_IS_OPEN (mixer)) {
+ g_free (mixer->device);
+ mixer->device = g_value_dup_string (value);
+ /* unset any cached device-name */
+ g_free (mixer->device_name);
+ mixer->device_name = NULL;
+ } else {
+ g_warning ("%s: can't change \"device\" property while mixer is open",
+ GST_OBJECT_NAME (mixer));
+ }
+ GST_OBJECT_UNLOCK (mixer);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_oss4_mixer_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstOss4Mixer *mixer = GST_OSS4_MIXER (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ GST_OBJECT_LOCK (mixer);
+ g_value_set_string (value, mixer->device);
+ GST_OBJECT_UNLOCK (mixer);
+ break;
+ case PROP_DEVICE_NAME:
+ GST_OBJECT_LOCK (mixer);
+ /* If device is set, try to retrieve the name even if we're not open */
+ if (mixer->fd == -1 && mixer->device != NULL) {
+ if (gst_oss4_mixer_open (mixer, TRUE)) {
+ g_value_set_string (value, mixer->device_name);
+ gst_oss4_mixer_close (mixer);
+ } else {
+ g_value_set_string (value, mixer->device_name);
+ }
+ } else {
+ g_value_set_string (value, mixer->device_name);
+ }
+ GST_OBJECT_UNLOCK (mixer);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+gst_oss4_mixer_open (GstOss4Mixer * mixer, gboolean silent_errors)
+{
+ struct oss_mixerinfo mi = { 0, };
+ gchar *device;
+
+ g_return_val_if_fail (!GST_OSS4_MIXER_IS_OPEN (mixer), FALSE);
+
+ if (mixer->device)
+ device = g_strdup (mixer->device);
+ else
+ device = gst_oss4_audio_find_device (GST_OBJECT_CAST (mixer));
+
+ /* desperate times, desperate measures */
+ if (device == NULL)
+ device = g_strdup ("/dev/mixer");
+
+ GST_INFO_OBJECT (mixer, "Trying to open OSS4 mixer device '%s'", device);
+
+ mixer->fd = open (device, O_RDWR, 0);
+ if (mixer->fd < 0)
+ goto open_failed;
+
+ /* Make sure it's OSS4. If it's old OSS, let the old ossmixer handle it */
+ if (!gst_oss4_audio_check_version (GST_OBJECT (mixer), mixer->fd))
+ goto legacy_oss;
+
+ GST_INFO_OBJECT (mixer, "Opened mixer device '%s', which is mixer %d",
+ device, mi.dev);
+
+ /* Get device name for currently open fd */
+ mi.dev = -1;
+ if (ioctl (mixer->fd, SNDCTL_MIXERINFO, &mi) == 0) {
+ mixer->modify_counter = mi.modify_counter;
+ if (mi.name[0] != '\0') {
+ mixer->device_name = g_strdup (mi.name);
+ }
+ } else {
+ mixer->modify_counter = 0;
+ }
+
+ if (mixer->device_name == NULL) {
+ mixer->device_name = g_strdup ("Unknown");
+ }
+ GST_INFO_OBJECT (mixer, "device name = '%s'", mixer->device_name);
+
+ mixer->open_device = device;
+
+ return TRUE;
+
+ /* ERRORS */
+open_failed:
+ {
+ if (!silent_errors) {
+ GST_ELEMENT_ERROR (mixer, RESOURCE, OPEN_READ_WRITE,
+ (_("Could not open audio device for mixer control handling.")),
+ GST_ERROR_SYSTEM);
+ } else {
+ GST_DEBUG_OBJECT (mixer, "open failed: %s (ignoring errors)",
+ g_strerror (errno));
+ }
+ g_free (device);
+ return FALSE;
+ }
+legacy_oss:
+ {
+ gst_oss4_mixer_close (mixer);
+ if (!silent_errors) {
+ GST_ELEMENT_ERROR (mixer, RESOURCE, OPEN_READ_WRITE,
+ (_("Could not open audio device for mixer control handling. "
+ "This version of the Open Sound System is not supported by this "
+ "element.")), ("Try the 'ossmixer' element instead"));
+ } else {
+ GST_DEBUG_OBJECT (mixer, "open failed: legacy oss (ignoring errors)");
+ }
+ g_free (device);
+ return FALSE;
+ }
+}
+
+static void
+gst_oss4_mixer_control_free (GstOss4MixerControl * mc)
+{
+ g_list_free (mc->children);
+ g_list_free (mc->mute_group);
+ g_free (mc->enum_vals);
+ memset (mc, 0, sizeof (GstOss4MixerControl));
+ g_free (mc);
+}
+
+static void
+gst_oss4_mixer_free_tracks (GstOss4Mixer * mixer)
+{
+ g_list_foreach (mixer->tracks, (GFunc) g_object_unref, NULL);
+ g_list_free (mixer->tracks);
+ mixer->tracks = NULL;
+
+ g_list_foreach (mixer->controls, (GFunc) gst_oss4_mixer_control_free, NULL);
+ g_list_free (mixer->controls);
+ mixer->controls = NULL;
+}
+
+static void
+gst_oss4_mixer_close (GstOss4Mixer * mixer)
+{
+ g_free (mixer->device_name);
+ mixer->device_name = NULL;
+
+ g_free (mixer->open_device);
+ mixer->open_device = NULL;
+
+ gst_oss4_mixer_free_tracks (mixer);
+
+ if (mixer->fd != -1) {
+ close (mixer->fd);
+ mixer->fd = -1;
+ }
+
+ gst_oss4_mixer_reset (mixer);
+}
+
+static void
+gst_oss4_mixer_watch_process_changes (GstOss4Mixer * mixer)
+{
+ GList *c, *t, *tracks = NULL;
+
+ GST_INFO_OBJECT (mixer, "mixer interface or control changed");
+
+ /* this is all with the mixer object lock held */
+
+ /* we go through the list backwards so we can bail out faster when the entire
+ * interface needs to be rebuilt */
+ for (c = g_list_last (mixer->controls); c != NULL; c = c->prev) {
+ GstOss4MixerControl *mc = c->data;
+ oss_mixer_value ossval = { 0, };
+
+ mc->changed = FALSE;
+ mc->list_changed = FALSE;
+
+ /* not interested in controls we don't expose in the mixer interface */
+ if (!mc->used)
+ continue;
+
+ /* don't try to read a value from controls that don't have one */
+ if (mc->mixext.type == MIXT_DEVROOT || mc->mixext.type == MIXT_GROUP)
+ continue;
+
+ /* is this an enum control whose list may change? */
+ if (mc->mixext.type == MIXT_ENUM && mc->enum_version != 0) {
+ if (gst_oss4_mixer_enum_control_update_enum_list (mixer, mc))
+ mc->list_changed = TRUE;
+ }
+
+ ossval.dev = mc->mixext.dev;
+ ossval.ctrl = mc->mixext.ctrl;
+ ossval.timestamp = mc->mixext.timestamp;
+
+ if (ioctl (mixer->fd, SNDCTL_MIX_READ, &ossval) == -1) {
+ if (errno == EIDRM || errno == EFAULT) {
+ GST_DEBUG ("%s has disappeared", mc->mixext.extname);
+ goto mixer_changed;
+ }
+ GST_WARNING_OBJECT (mixer, "MIX_READ failed: %s", g_strerror (errno));
+ /* just ignore, move on to next one */
+ continue;
+ }
+
+ if (ossval.value == mc->last_val) { /* no change */
+ /* GST_LOG_OBJECT (mixer, "%s hasn't changed", mc->mixext.extname); */
+ continue;
+ }
+
+ mc->last_val = ossval.value;
+ GST_LOG_OBJECT (mixer, "%s changed value to %u 0x%08x",
+ mc->mixext.extname, ossval.value, ossval.value);
+ mc->changed = TRUE;
+ }
+
+ /* copy list and take track refs, so we can safely drop the object lock,
+ * which we need to do to be able to post messages on the bus */
+ tracks = g_list_copy (mixer->tracks);
+ g_list_foreach (tracks, (GFunc) g_object_ref, NULL);
+
+ GST_OBJECT_UNLOCK (mixer);
+
+ /* since we don't know (or want to know exactly) which controls belong to
+ * which track, we just go through the tracks one-by-one now and make them
+ * check themselves if any of their controls have changed and which messages
+ * to post on the bus as a result */
+ for (t = tracks; t != NULL; t = t->next) {
+ GstMixerTrack *track = t->data;
+
+ if (GST_IS_OSS4_MIXER_SLIDER (track)) {
+ gst_oss4_mixer_slider_process_change_unlocked (track);
+ } else if (GST_IS_OSS4_MIXER_SWITCH (track)) {
+ gst_oss4_mixer_switch_process_change_unlocked (track);
+ } else if (GST_IS_OSS4_MIXER_ENUM (track)) {
+ gst_oss4_mixer_enum_process_change_unlocked (track);
+ }
+
+ g_object_unref (track);
+ }
+ g_list_free (tracks);
+
+ GST_OBJECT_LOCK (mixer);
+ return;
+
+mixer_changed:
+ {
+ GST_OBJECT_UNLOCK (mixer);
+ gst_mixer_mixer_changed (GST_MIXER (mixer));
+ GST_OBJECT_LOCK (mixer);
+ return;
+ }
+}
+
+/* This thread watches the mixer for changes in a somewhat inefficient way
+ * (running an ioctl every half second or so). This is still better and
+ * cheaper than apps polling all tracks for changes a few times a second
+ * though. Needs more thought. There's probably (hopefully) a way to get
+ * notifications via the fd directly somehow. */
+static gpointer
+gst_oss4_mixer_watch_thread (gpointer thread_data)
+{
+ GstOss4Mixer *mixer = GST_OSS4_MIXER_CAST (thread_data);
+
+ GST_DEBUG_OBJECT (mixer, "watch thread running");
+
+ GST_OBJECT_LOCK (mixer);
+ while (!mixer->watch_shutdown) {
+ oss_mixerinfo mi = { 0, };
+ GTimeVal tv;
+
+ mi.dev = -1;
+ if (ioctl (mixer->fd, SNDCTL_MIXERINFO, &mi) == 0) {
+ if (mixer->modify_counter != mi.modify_counter) {
+ /* GST_LOG ("processing changes"); */
+ gst_oss4_mixer_watch_process_changes (mixer);
+ mixer->modify_counter = mi.modify_counter;
+ } else {
+ /* GST_LOG ("no changes"); */
+ }
+ } else {
+ GST_WARNING_OBJECT (mixer, "MIXERINFO failed: %s", g_strerror (errno));
+ }
+
+ /* we could move the _get_current_time out of the loop and just do the
+ * add in ever iteration, which would be less exact, but who cares */
+ g_get_current_time (&tv);
+ g_time_val_add (&tv, GST_OSS4_MIXER_WATCH_INTERVAL * 1000);
+ (void) g_cond_timed_wait (mixer->watch_cond, GST_OBJECT_GET_LOCK (mixer),
+ &tv);
+ }
+ GST_OBJECT_UNLOCK (mixer);
+
+ GST_DEBUG_OBJECT (mixer, "watch thread done");
+ gst_object_unref (mixer);
+ return NULL;
+}
+
+/* call with object lock held */
+static void
+gst_oss4_mixer_wake_up_watch_task (GstOss4Mixer * mixer)
+{
+ GST_LOG_OBJECT (mixer, "signalling watch thread to wake up");
+ g_cond_signal (mixer->watch_cond);
+}
+
+static void
+gst_oss4_mixer_stop_watch_task (GstOss4Mixer * mixer)
+{
+ if (mixer->watch_thread) {
+ GST_OBJECT_LOCK (mixer);
+ mixer->watch_shutdown = TRUE;
+ GST_LOG_OBJECT (mixer, "signalling watch thread to stop");
+ g_cond_signal (mixer->watch_cond);
+ GST_OBJECT_UNLOCK (mixer);
+ GST_LOG_OBJECT (mixer, "waiting for watch thread to join");
+ g_thread_join (mixer->watch_thread);
+ GST_DEBUG_OBJECT (mixer, "watch thread stopped");
+ mixer->watch_thread = NULL;
+ }
+
+ if (mixer->watch_cond) {
+ g_cond_free (mixer->watch_cond);
+ mixer->watch_cond = NULL;
+ }
+}
+
+static void
+gst_oss4_mixer_start_watch_task (GstOss4Mixer * mixer)
+{
+ GError *err = NULL;
+
+ mixer->watch_cond = g_cond_new ();
+ mixer->watch_shutdown = FALSE;
+
+#if !GLIB_CHECK_VERSION (2, 31, 0)
+ mixer->watch_thread = g_thread_create (gst_oss4_mixer_watch_thread,
+ gst_object_ref (mixer), TRUE, &err);
+#else
+ mixer->watch_thread = g_thread_try_new ("oss4-mixer-thread",
+ gst_oss4_mixer_watch_thread, gst_object_ref (mixer), &err);
+#endif
+
+ if (mixer->watch_thread == NULL) {
+ GST_ERROR_OBJECT (mixer, "Could not create watch thread: %s", err->message);
+ g_cond_free (mixer->watch_cond);
+ mixer->watch_cond = NULL;
+ g_error_free (err);
+ }
+}
+
+static GstStateChangeReturn
+gst_oss4_mixer_change_state (GstElement * element, GstStateChange transition)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ GstOss4Mixer *mixer = GST_OSS4_MIXER (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ if (!gst_oss4_mixer_open (mixer, FALSE))
+ return GST_STATE_CHANGE_FAILURE;
+ gst_oss4_mixer_start_watch_task (mixer);
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ gst_oss4_mixer_stop_watch_task (mixer);
+ gst_oss4_mixer_close (mixer);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/* === GstMixer interface === */
+
+static inline gboolean
+gst_oss4_mixer_contains_track (GstMixer * mixer, GstMixerTrack * track)
+{
+ return (g_list_find (GST_OSS4_MIXER (mixer)->tracks, track) != NULL);
+}
+
+static inline gboolean
+gst_oss4_mixer_contains_options (GstMixer * mixer, GstMixerOptions * options)
+{
+ return (g_list_find (GST_OSS4_MIXER (mixer)->tracks, options) != NULL);
+}
+
+static void
+gst_oss4_mixer_post_mixer_changed_msg (GstOss4Mixer * mixer)
+{
+ /* only post mixer-changed message once */
+ if (!mixer->need_update) {
+ gst_mixer_mixer_changed (GST_MIXER (mixer));
+ mixer->need_update = TRUE;
+ }
+}
+
+/* call with mixer object lock held to serialise ioctl */
+gboolean
+gst_oss4_mixer_get_control_val (GstOss4Mixer * mixer, GstOss4MixerControl * mc,
+ int *val)
+{
+ oss_mixer_value ossval = { 0, };
+
+ if (GST_OBJECT_TRYLOCK (mixer)) {
+ GST_ERROR ("must be called with mixer lock held");
+ GST_OBJECT_UNLOCK (mixer);
+ }
+
+ ossval.dev = mc->mixext.dev;
+ ossval.ctrl = mc->mixext.ctrl;
+ ossval.timestamp = mc->mixext.timestamp;
+
+ if (ioctl (mixer->fd, SNDCTL_MIX_READ, &ossval) == -1) {
+ if (errno == EIDRM) {
+ GST_DEBUG_OBJECT (mixer, "MIX_READ failed: mixer interface has changed");
+ gst_oss4_mixer_post_mixer_changed_msg (mixer);
+ } else {
+ GST_WARNING_OBJECT (mixer, "MIX_READ failed: %s", g_strerror (errno));
+ }
+ *val = 0;
+ mc->last_val = 0;
+ return FALSE;
+ }
+
+ *val = ossval.value;
+ mc->last_val = ossval.value;
+ GST_LOG_OBJECT (mixer, "got value 0x%08x from %s)", *val, mc->mixext.extname);
+ return TRUE;
+}
+
+/* call with mixer object lock held to serialise ioctl */
+gboolean
+gst_oss4_mixer_set_control_val (GstOss4Mixer * mixer, GstOss4MixerControl * mc,
+ int val)
+{
+ oss_mixer_value ossval = { 0, };
+
+ ossval.dev = mc->mixext.dev;
+ ossval.ctrl = mc->mixext.ctrl;
+ ossval.timestamp = mc->mixext.timestamp;
+ ossval.value = val;
+
+ if (GST_OBJECT_TRYLOCK (mixer)) {
+ GST_ERROR ("must be called with mixer lock held");
+ GST_OBJECT_UNLOCK (mixer);
+ }
+
+ if (ioctl (mixer->fd, SNDCTL_MIX_WRITE, &ossval) == -1) {
+ if (errno == EIDRM) {
+ GST_LOG_OBJECT (mixer, "MIX_WRITE failed: mixer interface has changed");
+ gst_oss4_mixer_post_mixer_changed_msg (mixer);
+ } else {
+ GST_WARNING_OBJECT (mixer, "MIX_WRITE failed: %s", g_strerror (errno));
+ }
+ return FALSE;
+ }
+
+ mc->last_val = val;
+ GST_LOG_OBJECT (mixer, "set value 0x%08x on %s", val, mc->mixext.extname);
+ return TRUE;
+}
+
+#if 0
+static gchar *
+gst_oss4_mixer_control_get_pretty_name (GstOss4MixerControl * mc)
+{
+ gchar *name;
+
+ const gchar *name, *u;
+
+ /* "The id field is the original name given by the driver when it called
+ * mixer_ext_create_control. This name can be used by fully featured GUI
+ * mixers. However this name should be downshifted and cut before the last
+ * underscore ("_") to get the proper name. For example mixer control name
+ * created as "MYDRV_MAINVOL" will become just "mainvol" after this
+ * transformation." */
+ name = mc->mixext.extname;
+ u = MAX (strrchr (name, '_'), strrchr (name, '.'));
+ if (u != NULL)
+ name = u + 1;
+
+ /* maybe capitalize the first letter? */
+ return g_ascii_strdown (name, -1);
+ /* the .id thing doesn't really seem to work right, ie. for some sliders
+ * it's just '-' so you have to use the name of the parent control etc.
+ * let's not use it for now, much too painful. */
+ if (g_str_has_prefix (mc->mixext.extname, "misc."))
+ name = g_strdup (mc->mixext.extname + 5);
+ else
+ name = g_strdup (mc->mixext.extname);
+ /* chop off trailing digit (only one for now) */
+ if (strlen (name) > 0 && g_ascii_isdigit (name[strlen (name) - 1]))
+ name[strlen (name) - 1] = '\0';
+ g_strdelimit (name, ".", ' ');
+ return name;
+}
+#endif
+
+/* these translations are a bit ad-hoc and horribly incomplete; it is not
+ * really going to work this way with all the different chipsets and drivers.
+ * We also use these for translating option values. */
+static struct
+{
+ const gchar oss_name[32];
+ const gchar *label;
+} labels[] = {
+ {
+ "volume", N_("Volume")}, {
+ "master", N_("Master")}, {
+ "front", N_("Front")}, {
+ "rear", N_("Rear")}, {
+ "headphones", N_("Headphones")}, {
+ "center", N_("Center")}, {
+ "lfe", N_("LFE")}, {
+ "surround", N_("Surround")}, {
+ "side", N_("Side")}, {
+ "speaker", N_("Built-in Speaker")}, {
+ "aux1-out", N_("AUX 1 Out")}, {
+ "aux2-out", N_("AUX 2 Out")}, {
+ "aux-out", N_("AUX Out")}, {
+ "bass", N_("Bass")}, {
+ "treble", N_("Treble")}, {
+ "3d-depth", N_("3D Depth")}, {
+ "3d-center", N_("3D Center")}, {
+ "3d-enhance", N_("3D Enhance")}, {
+ "phone", N_("Telephone")}, {
+ "mic", N_("Microphone")}, {
+ "line-out", N_("Line Out")}, {
+ "line-in", N_("Line In")}, {
+ "linein", N_("Line In")}, {
+ "cd", N_("Internal CD")}, {
+ "video", N_("Video In")}, {
+ "aux1-in", N_("AUX 1 In")}, {
+ "aux2-in", N_("AUX 2 In")}, {
+ "aux-in", N_("AUX In")}, {
+ "pcm", N_("PCM")}, {
+ "record-gain", N_("Record Gain")}, {
+ "igain", N_("Record Gain")}, {
+ "ogain", N_("Output Gain")}, {
+ "micboost", N_("Microphone Boost")}, {
+ "loopback", N_("Loopback")}, {
+ "diag", N_("Diagnostic")}, {
+ "loudness", N_("Bass Boost")}, {
+ "outputs", N_("Playback Ports")}, {
+ "input", N_("Input")}, {
+ "inputs", N_("Record Source")}, {
+ "record-source", N_("Record Source")}, {
+ "monitor-source", N_("Monitor Source")}, {
+ "beep", N_("Keyboard Beep")}, {
+ "monitor-gain", N_("Monitor")}, {
+ "stereo-simulate", N_("Simulate Stereo")}, {
+ "stereo", N_("Stereo")}, {
+ "multich", N_("Surround Sound")}, {
+ "mic-gain", N_("Microphone Gain")}, {
+ "speaker-source", N_("Speaker Source")}, {
+ "mic-source", N_("Microphone Source")}, {
+ "jack", N_("Jack")}, {
+ "center/lfe", N_("Center / LFE")}, {
+ "stereo-mix", N_("Stereo Mix")}, {
+ "mono-mix", N_("Mono Mix")}, {
+ "input-mix", N_("Input Mix")}, {
+ "spdif-in", N_("SPDIF In")}, {
+ "spdif-out", N_("SPDIF Out")}, {
+ "mic1", N_("Microphone 1")}, {
+ "mic2", N_("Microphone 2")}, {
+ "digital-out", N_("Digital Out")}, {
+ "digital-in", N_("Digital In")}, {
+ "hdmi", N_("HDMI")}, {
+ "modem", N_("Modem")}, {
+ "handset", N_("Handset")}, {
+ "other", N_("Other")}, {
+ "stereo", N_("Stereo")}, {
+ "none", N_("None")}, {
+ "on", N_("On")}, {
+ "off", N_("Off")}, {
+ "mute", N_("Mute")}, {
+ "fast", N_("Fast")}, {
+ /* TRANSLATORS: "Very Low" is a quality setting here */
+ "very-low", N_("Very Low")}, {
+ /* TRANSLATORS: "Low" is a quality setting here */
+ "low", N_("Low")}, {
+ /* TRANSLATORS: "Medium" is a quality setting here */
+ "medium", N_("Medium")}, {
+ /* TRANSLATORS: "High" is a quality setting here */
+ "high", N_("High")}, {
+ /* TRANSLATORS: "Very High" is a quality setting here */
+ "very-high", N_("Very High")}, {
+ "high+", N_("Very High")}, {
+ /* TRANSLATORS: "Production" is a quality setting here */
+ "production", N_("Production")}, {
+ "fp-mic", N_("Front Panel Microphone")}, {
+ "fp-linein", N_("Front Panel Line In")}, {
+ "fp-headphones", N_("Front Panel Headphones")}, {
+ "fp-lineout", N_("Front Panel Line Out")}, {
+ "green", N_("Green Connector")}, {
+ "pink", N_("Pink Connector")}, {
+ "blue", N_("Blue Connector")}, {
+ "white", N_("White Connector")}, {
+ "black", N_("Black Connector")}, {
+ "gray", N_("Gray Connector")}, {
+ "orange", N_("Orange Connector")}, {
+ "red", N_("Red Connector")}, {
+ "yellow", N_("Yellow Connector")}, {
+ "fp-green", N_("Green Front Panel Connector")}, {
+ "fp-pink", N_("Pink Front Panel Connector")}, {
+ "fp-blue", N_("Blue Front Panel Connector")}, {
+ "fp-white", N_("White Front Panel Connector")}, {
+ "fp-black", N_("Black Front Panel Connector")}, {
+ "fp-gray", N_("Gray Front Panel Connector")}, {
+ "fp-orange", N_("Orange Front Panel Connector")}, {
+ "fp-red", N_("Red Front Panel Connector")}, {
+ "fp-yellow", N_("Yellow Front Panel Connector")}, {
+ "spread", N_("Spread Output")}, {
+ "downmix", N_("Downmix")},
+ /* FIXME translate Audigy NX USB labels) */
+/*
+ { "rec.src", N_("Record Source") },
+ { "output.mute", N_("Mute output") }
+ headph (Controller group)
+ headph.src (Enumeration control)
+ headph.mute (On/Off switch)
+ digital2 (Controller group)
+ digital2.src (Enumeration control)
+ digital2.mute (On/Off switch)
+ digital (Controller group)
+ digital.mute1 (On/Off switch)
+ digital.vol (Controller group)
+ digital.vol.front (Stereo slider (0-255))
+ digital.vol.surr (Stereo slider (0-255))
+ digital.vol.c/l (Stereo slider (0-255))
+ digital.vol.center (Stereo slider (0-255))
+ digital.mute2 (On/Off switch)
+ digital.vol (Stereo slider (0-255))
+ line (Controller group)
+ line.mute (On/Off switch)
+ line.vol (Stereo slider (0-255))
+ play-altset (Enumeration control)
+ rec-altset (Enumeration control)
+*/
+};
+
+/* Decent i18n is pretty much impossible with OSS's way of providing us with
+ * mixer labels (and the fact that they are pretty much random), but that
+ * doesn't mean we shouldn't at least try. */
+static gchar *
+gst_oss4_mixer_control_get_translated_name (GstOss4MixerControl * mc)
+{
+ gchar name[128] = { 0, };
+ gchar vmix_str[32] = { '\0', };
+ gchar *ptr;
+ int dummy, i;
+ int num = -1;
+ gboolean function_suffix = FALSE;
+
+ /* main virtual mixer controls (we hide the stream volumes) */
+ if (sscanf (mc->mixext.extname, "vmix%d-%32c", &dummy, vmix_str) == 2) {
+ if (strcmp (vmix_str, "src") == 0)
+ return g_strdup (_("Virtual Mixer Input"));
+ else if (strcmp (vmix_str, "vol") == 0)
+ return g_strdup (_("Virtual Mixer Output"));
+ else if (strcmp (vmix_str, "channels") == 0)
+ return g_strdup (_("Virtual Mixer Channels"));
+ }
+
+ g_strlcpy (name, mc->mixext.extname, sizeof (name));
+
+ /* we deal with either "connector." or "jack." */
+ if ((g_str_has_prefix (name, "connector.")) ||
+ (g_str_has_prefix (name, "jack."))) {
+ ptr = strchr (mc->mixext.extname, '.');
+ ptr++;
+ g_strlcpy (name, ptr, sizeof (name));
+ }
+
+ /* special handling for jack retasking suffixes */
+ if (g_str_has_suffix (name, ".function") || g_str_has_suffix (name, ".mode")) {
+ function_suffix = TRUE;
+ ptr = strrchr (name, '.');
+ *ptr = 0;
+ }
+
+ /* parse off trailing numbers */
+ i = strlen (name);
+ while ((i > 0) && (g_ascii_isdigit (name[i - 1]))) {
+ i--;
+ }
+ /* the check catches the case where the control name is just a number */
+ if ((i > 0) && (name[i] != '\0')) {
+ num = atoi (name + i);
+ name[i] = '\0';
+ }
+
+ /* look for a match, progressively skipping '.' delimited prefixes as we go */
+ ptr = name;
+ do {
+ if (*ptr == '.')
+ ptr++;
+ for (i = 0; i < G_N_ELEMENTS (labels); ++i) {
+ if (g_ascii_strcasecmp (ptr, labels[i].oss_name) == 0) {
+ g_strlcpy (name, _(labels[i].label), sizeof (name));
+ goto append_suffixes;
+ }
+ }
+ } while ((ptr = strchr (ptr, '.')) != NULL);
+
+ /* failing that, just replace periods with spaces */
+ g_strdelimit (name, ".", ' ');
+
+append_suffixes:
+ if (num > -1) {
+ if (function_suffix) {
+ /* TRANSLATORS: name + number of a volume mixer control */
+ return g_strdup_printf (_("%s %d Function"), name, num);
+ } else {
+ return g_strdup_printf ("%s %d", name, num);
+ }
+ } else {
+ if (function_suffix) {
+ /* TRANSLATORS: name of a volume mixer control */
+ return g_strdup_printf (_("%s Function"), name);
+ } else {
+ return g_strdup (name);
+ }
+ }
+}
+
+static const gchar *
+gst_oss4_mixer_control_get_translated_option (const gchar * name)
+{
+ int i;
+ for (i = 0; i < G_N_ELEMENTS (labels); ++i) {
+ if (g_ascii_strcasecmp (name, labels[i].oss_name) == 0) {
+ return _(labels[i].label);
+ }
+ }
+ return (name);
+}
+
+#ifndef GST_DISABLE_GST_DEBUG
+static const gchar *
+mixer_ext_type_get_name (gint type)
+{
+ switch (type) {
+ case MIXT_DEVROOT:
+ return "Device root entry";
+ case MIXT_GROUP:
+ return "Controller group";
+ case MIXT_ONOFF:
+ return "On/Off switch";
+ case MIXT_ENUM:
+ return "Enumeration control";
+ case MIXT_MONOSLIDER:
+ return "Mono slider (0-255)";
+ case MIXT_STEREOSLIDER:
+ return "Stereo slider (0-255)";
+ case MIXT_MESSAGE:
+ return "Textual message"; /* whatever this is */
+ case MIXT_MONOVU:
+ return "Mono VU meter value";
+ case MIXT_STEREOVU:
+ return "Stereo VU meter value";
+ case MIXT_MONOPEAK:
+ return "Mono VU meter peak value";
+ case MIXT_STEREOPEAK:
+ return "Stereo VU meter peak value";
+ case MIXT_RADIOGROUP:
+ return "Radio button group";
+ case MIXT_MARKER: /* Separator between normal and extension entries */
+ return "Separator";
+ case MIXT_VALUE:
+ return "Decimal value entry";
+ case MIXT_HEXVALUE:
+ return "Hex value entry";
+ case MIXT_SLIDER:
+ return "Mono slider (31-bit value range)";
+ case MIXT_3D:
+ return "3D"; /* what's this? */
+ case MIXT_MONOSLIDER16:
+ return "Mono slider (0-32767)";
+ case MIXT_STEREOSLIDER16:
+ return "Stereo slider (0-32767)";
+ case MIXT_MUTE:
+ return "Mute switch";
+ default:
+ break;
+ }
+ return "unknown";
+}
+#endif /* GST_DISABLE_GST_DEBUG */
+
+#ifndef GST_DISABLE_GST_DEBUG
+static const gchar *
+mixer_ext_flags_get_string (gint flags)
+{
+ struct
+ {
+ gint flag;
+ gchar nick[16];
+ } all_flags[] = {
+ /* first the important ones */
+ {
+ MIXF_MAINVOL, "MAINVOL"}, {
+ MIXF_PCMVOL, "PCMVOL"}, {
+ MIXF_RECVOL, "RECVOL"}, {
+ MIXF_MONVOL, "MONVOL"}, {
+ MIXF_DESCR, "DESCR"},
+ /* now the rest in the right order */
+ {
+ MIXF_READABLE, "READABLE"}, {
+ MIXF_WRITEABLE, "WRITABLE"}, {
+ MIXF_POLL, "POLL"}, {
+ MIXF_HZ, "HZ"}, {
+ MIXF_STRING, "STRING"}, {
+ MIXF_DYNAMIC, "DYNAMIC"}, {
+ MIXF_OKFAIL, "OKFAIL"}, {
+ MIXF_FLAT, "FLAT"}, {
+ MIXF_LEGACY, "LEGACY"}, {
+ MIXF_CENTIBEL, "CENTIBEL"}, {
+ MIXF_DECIBEL, "DECIBEL"}, {
+ MIXF_WIDE, "WIDE"}
+ };
+ GString *s;
+ GQuark q;
+ gint i;
+
+ if (flags == 0)
+ return "None";
+
+ s = g_string_new ("");
+ for (i = 0; i < G_N_ELEMENTS (all_flags); ++i) {
+ if ((flags & all_flags[i].flag)) {
+ if (s->len > 0)
+ g_string_append (s, " | ");
+ g_string_append (s, all_flags[i].nick);
+ flags &= ~all_flags[i].flag; /* unset */
+ }
+ }
+
+ /* unknown flags? */
+ if (flags != 0) {
+ if (s->len > 0)
+ g_string_append (s, " | ");
+ g_string_append (s, "???");
+ }
+
+ /* we'll just put it into the global quark table (cheeky, eh?) */
+ q = g_quark_from_string (s->str);
+ g_string_free (s, TRUE);
+
+ return g_quark_to_string (q);
+}
+#endif /* GST_DISABLE_GST_DEBUG */
+
+#ifndef GST_DISABLE_GST_DEBUG
+static void
+gst_oss4_mixer_control_dump_tree (GstOss4MixerControl * mc, gint depth)
+{
+ GList *c;
+ gchar spaces[64];
+ gint i;
+
+ depth = MIN (sizeof (spaces) - 1, depth);
+ for (i = 0; i < depth; ++i)
+ spaces[i] = ' ';
+ spaces[i] = '\0';
+
+ GST_LOG ("%s%s (%s)", spaces, mc->mixext.extname,
+ mixer_ext_type_get_name (mc->mixext.type));
+ for (c = mc->children; c != NULL; c = c->next) {
+ GstOss4MixerControl *child_mc = (GstOss4MixerControl *) c->data;
+
+ gst_oss4_mixer_control_dump_tree (child_mc, depth + 2);
+ }
+}
+#endif /* GST_DISABLE_GST_DEBUG */
+
+static GList *
+gst_oss4_mixer_get_controls (GstOss4Mixer * mixer)
+{
+ GstOss4MixerControl *root_mc = NULL;
+ oss_mixerinfo mi = { 0, };
+ GList *controls = NULL;
+ GList *l;
+ guint i;
+
+ /* Get info for currently open fd */
+ mi.dev = -1;
+ if (ioctl (mixer->fd, SNDCTL_MIXERINFO, &mi) == -1)
+ goto no_mixerinfo;
+
+ if (mi.nrext <= 0) {
+ GST_DEBUG ("mixer %s has no controls", mi.id);
+ return NULL;
+ }
+
+ GST_INFO ("Reading controls for mixer %s", mi.id);
+
+ for (i = 0; i < mi.nrext; ++i) {
+ GstOss4MixerControl *mc;
+ oss_mixext mix_ext = { 0, };
+
+ mix_ext.dev = mi.dev;
+ mix_ext.ctrl = i;
+
+ if (ioctl (mixer->fd, SNDCTL_MIX_EXTINFO, &mix_ext) == -1) {
+ GST_DEBUG ("SNDCTL_MIX_EXTINFO failed on mixer %s, control %d: %s",
+ mi.id, i, g_strerror (errno));
+ continue;
+ }
+
+ /* if this is the last one, save it for is-interface-up-to-date checking */
+ if (i == mi.nrext)
+ mixer->last_mixext = mix_ext;
+
+ mc = g_new0 (GstOss4MixerControl, 1);
+ mc->mixext = mix_ext;
+
+ /* both control_no and desc fields are pretty useless, ie. not always set,
+ * if ever, so not listed here */
+ GST_INFO ("Control %d", mix_ext.ctrl);
+ GST_INFO (" name : %s", mix_ext.extname);
+ GST_INFO (" type : %s (%d)", mixer_ext_type_get_name (mix_ext.type),
+ mix_ext.type);
+ GST_INFO (" flags : %s (0x%04x)",
+ mixer_ext_flags_get_string (mix_ext.flags), mix_ext.flags);
+ GST_INFO (" parent : %d", mix_ext.parent);
+
+ if (!MIXEXT_IS_ROOT (mix_ext)) {
+ /* find parent (we assume it comes in the list before the child) */
+ for (l = controls; l != NULL; l = l->next) {
+ GstOss4MixerControl *parent_mc = (GstOss4MixerControl *) l->data;
+
+ if (parent_mc->mixext.ctrl == mix_ext.parent) {
+ mc->parent = parent_mc;
+ parent_mc->children = g_list_append (parent_mc->children, mc);
+ break;
+ }
+ }
+ if (mc->parent == NULL) {
+ GST_ERROR_OBJECT (mixer, "couldn't find parent for control %d", i);
+ g_free (mc);
+ continue;
+ }
+ } else if (root_mc == NULL) {
+ root_mc = mc;
+ } else {
+ GST_WARNING_OBJECT (mixer, "two root controls?!");
+ }
+
+ controls = g_list_prepend (controls, mc);
+ }
+
+#ifndef GST_DISABLE_GST_DEBUG
+ gst_oss4_mixer_control_dump_tree (root_mc, 0);
+#endif
+
+ return g_list_reverse (controls);
+
+/* ERRORS */
+no_mixerinfo:
+ {
+ GST_WARNING ("SNDCTL_MIXERINFO failed on mixer device %s: %s", mi.id,
+ g_strerror (errno));
+ return NULL;
+ }
+}
+
+static void
+gst_oss4_mixer_controls_guess_master (GstOss4Mixer * mixer,
+ const GList * controls)
+{
+ GstOss4MixerControl *master_mc = NULL;
+ const GList *l;
+
+ for (l = controls; l != NULL; l = l->next) {
+ GstOss4MixerControl *mc = (GstOss4MixerControl *) l->data;
+
+ /* do we need to check if it's a slider type here? */
+ if ((mc->mixext.flags & MIXF_PCMVOL)) {
+ GST_INFO_OBJECT (mixer, "First PCM control: %s", mc->mixext.extname);
+ master_mc = mc;
+ break;
+ }
+
+ if (((mc->mixext.flags & MIXF_MAINVOL)) && master_mc == NULL) {
+ GST_INFO_OBJECT (mixer, "First main volume control: %s",
+ mc->mixext.extname);
+ master_mc = mc;
+ }
+ }
+
+ if (master_mc != NULL)
+ master_mc->is_master = TRUE;
+}
+
+/* type: -1 for all types, otherwise just return siblings with requested type */
+static GList *
+gst_oss4_mixer_control_get_siblings (GstOss4MixerControl * mc, gint type)
+{
+ GList *s, *siblings = NULL;
+
+ if (mc->parent == NULL)
+ return NULL;
+
+ for (s = mc->parent->children; s != NULL; s = s->next) {
+ GstOss4MixerControl *sibling = (GstOss4MixerControl *) s->data;
+
+ if (mc != sibling && (type < 0 || sibling->mixext.type == type))
+ siblings = g_list_append (siblings, sibling);
+ }
+
+ return siblings;
+}
+
+static void
+gst_oss4_mixer_controls_find_sliders (GstOss4Mixer * mixer,
+ const GList * controls)
+{
+ const GList *l;
+
+ for (l = controls; l != NULL; l = l->next) {
+ GstOss4MixerControl *mc = (GstOss4MixerControl *) l->data;
+ GList *s, *siblings;
+
+ if (!MIXEXT_IS_SLIDER (mc->mixext) || mc->parent == NULL || mc->used)
+ continue;
+
+ mc->is_slider = TRUE;
+ mc->used = TRUE;
+
+ siblings = gst_oss4_mixer_control_get_siblings (mc, -1);
+
+ /* Note: the names can be misleading and may not reflect the actual
+ * hierarchy of the controls, e.g. it's possible that a slider is called
+ * connector.green and the mute control then connector.green.mute, but
+ * both controls are in fact siblings and both children of the group
+ * 'green' instead of mute being a child of connector.green as the naming
+ * would seem to suggest */
+ GST_LOG ("Slider: %s, parent=%s, %d siblings", mc->mixext.extname,
+ mc->parent->mixext.extname, g_list_length (siblings));
+
+ for (s = siblings; s != NULL; s = s->next) {
+ GstOss4MixerControl *sibling = (GstOss4MixerControl *) s->data;
+
+ GST_LOG (" %s (%s)", sibling->mixext.extname,
+ mixer_ext_type_get_name (sibling->mixext.type));
+
+ if (sibling->mixext.type == MIXT_MUTE ||
+ g_str_has_suffix (sibling->mixext.extname, ".mute")) {
+ /* simple case: slider with single mute sibling. We assume the .mute
+ * suffix in the name won't change - can't really do much else anyway */
+ if (sibling->mixext.type == MIXT_ONOFF ||
+ sibling->mixext.type == MIXT_MUTE) {
+ GST_LOG (" mute control for %s is %s", mc->mixext.extname,
+ sibling->mixext.extname);
+ mc->mute = sibling;
+ sibling->used = TRUE;
+ }
+ /* a group of .mute controls. We assume they are all switches here */
+ if (sibling->mixext.type == MIXT_GROUP) {
+ GList *m;
+
+ for (m = sibling->children; m != NULL; m = m->next) {
+ GstOss4MixerControl *grouped_sibling = m->data;
+
+ if (grouped_sibling->mixext.type == MIXT_ONOFF ||
+ grouped_sibling->mixext.type == MIXT_MUTE) {
+ GST_LOG (" %s is grouped mute control for %s",
+ grouped_sibling->mixext.extname, mc->mixext.extname);
+ mc->mute_group = g_list_append (mc->mute_group, grouped_sibling);
+ }
+ }
+
+ GST_LOG (" %s has a group of %d mute controls",
+ mc->mixext.extname, g_list_length (mc->mute_group));
+
+ /* we don't mark the individual mute controls as used, only the
+ * group control, as we still want individual switches for the
+ * individual controls */
+ sibling->used = TRUE;
+ }
+ }
+ }
+ g_list_free (siblings);
+ }
+}
+
+/* should be called with the mixer object lock held because of the ioctl;
+ * returns TRUE if the list was read the first time or modified */
+static gboolean
+gst_oss4_mixer_enum_control_update_enum_list (GstOss4Mixer * mixer,
+ GstOss4MixerControl * mc)
+{
+ oss_mixer_enuminfo ei = { 0, };
+ guint num_existing = 0;
+ int i;
+
+ /* count and existing values */
+ while (mc->enum_vals != NULL && mc->enum_vals[num_existing] != 0)
+ ++num_existing;
+
+ ei.dev = mc->mixext.dev;
+ ei.ctrl = mc->mixext.ctrl;
+
+ /* if we have create a generic list with numeric IDs already and the
+ * number of values hasn't changed, then there's not much to do here */
+ if (mc->no_list && mc->enum_vals != NULL &&
+ num_existing == mc->mixext.maxvalue) {
+ return FALSE;
+ }
+
+ /* if we have a list and it doesn't change, there's nothing to do either */
+ if (mc->enum_vals != NULL && mc->enum_version == 0)
+ return FALSE;
+
+ if (ioctl (mixer->fd, SNDCTL_MIX_ENUMINFO, &ei) == -1) {
+ g_free (mc->enum_vals);
+ mc->enum_vals = g_new0 (GQuark, mc->mixext.maxvalue + 1);
+
+ GST_DEBUG ("no enum info available, creating numeric values from 0-%d",
+ mc->mixext.maxvalue - 1);
+
+ /* "It is possible that some enum controls don't have any name list
+ * available. In this case the application should automatically generate
+ * list of numbers (0 to N-1)" */
+ for (i = 0; i < mc->mixext.maxvalue; ++i) {
+ gchar num_str[8];
+
+ g_snprintf (num_str, sizeof (num_str), "%d", i);
+ mc->enum_vals[i] = g_quark_from_string (num_str);
+ }
+ mc->enum_version = 0; /* the only way to change is via maxvalue */
+ } else {
+ /* old list same as current list? */
+ if (mc->enum_vals != NULL && mc->enum_version == ei.version)
+ return FALSE;
+
+ /* no list yet, or the list has changed */
+ GST_LOG ("%s", (mc->enum_vals) ? "enum list has changed" : "reading list");
+ if (ei.nvalues != mc->mixext.maxvalue) {
+ GST_WARNING_OBJECT (mixer, "Enum: %s, nvalues %d != maxvalue %d",
+ mc->mixext.extname, ei.nvalues, mc->mixext.maxvalue);
+ mc->mixext.maxvalue = MIN (ei.nvalues, mc->mixext.maxvalue);
+ }
+
+ mc->mixext.maxvalue = MIN (mc->mixext.maxvalue, OSS_ENUM_MAXVALUE);
+
+ g_free (mc->enum_vals);
+ mc->enum_vals = g_new0 (GQuark, mc->mixext.maxvalue + 1);
+ for (i = 0; i < mc->mixext.maxvalue; ++i) {
+ GST_LOG (" %s", ei.strings + ei.strindex[i]);
+ mc->enum_vals[i] =
+ g_quark_from_string (gst_oss4_mixer_control_get_translated_option
+ (ei.strings + ei.strindex[i]));
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+gst_oss4_mixer_controls_find_enums (GstOss4Mixer * mixer,
+ const GList * controls)
+{
+ const GList *l;
+
+ for (l = controls; l != NULL; l = l->next) {
+ GstOss4MixerControl *mc = (GstOss4MixerControl *) l->data;
+
+ if (mc->mixext.type != MIXT_ENUM || mc->used)
+ continue;
+
+ mc->is_enum = TRUE;
+ mc->used = TRUE;
+
+ /* Note: enums are special: for most controls, the maxvalue is inclusive,
+ * but for enum controls it's actually exclusive (boggle), so that
+ * mixext.maxvalue = num_values */
+
+ GST_LOG ("Enum: %s, parent=%s, num_enums=%d", mc->mixext.extname,
+ mc->parent->mixext.extname, mc->mixext.maxvalue);
+
+ gst_oss4_mixer_enum_control_update_enum_list (mixer, mc);
+ }
+}
+
+static void
+gst_oss4_mixer_controls_find_switches (GstOss4Mixer * mixer,
+ const GList * controls)
+{
+ const GList *l;
+
+ for (l = controls; l != NULL; l = l->next) {
+ GstOss4MixerControl *mc = (GstOss4MixerControl *) l->data;
+
+ if (mc->used)
+ continue;
+
+ if (mc->mixext.type != MIXT_ONOFF && mc->mixext.type != MIXT_MUTE)
+ continue;
+
+ mc->is_switch = TRUE;
+ mc->used = TRUE;
+
+ GST_LOG ("Switch: %s, parent=%s", mc->mixext.extname,
+ mc->parent->mixext.extname);
+ }
+}
+
+static void
+gst_oss4_mixer_controls_find_virtual (GstOss4Mixer * mixer,
+ const GList * controls)
+{
+ const GList *l;
+
+ for (l = controls; l != NULL; l = l->next) {
+ GstOss4MixerControl *mc = (GstOss4MixerControl *) l->data;
+
+ /* or sscanf (mc->mixext.extname, "vmix%d-out.", &n) == 1 ? */
+ /* for now we just flag all virtual controls with managed labels, those
+ * are really more appropriate for a pavucontrol-type control thing than
+ * the (more hardware-oriented) mixer interface */
+ if (mc->mixext.id[0] == '@') {
+ mc->is_virtual = TRUE;
+ GST_LOG ("%s is virtual control with managed label", mc->mixext.extname);
+ }
+ }
+}
+
+static void
+gst_oss4_mixer_controls_dump_unused (GstOss4Mixer * mixer,
+ const GList * controls)
+{
+ const GList *l;
+
+ for (l = controls; l != NULL; l = l->next) {
+ GstOss4MixerControl *mc = (GstOss4MixerControl *) l->data;
+
+ if (mc->used)
+ continue;
+
+ switch (mc->mixext.type) {
+ case MIXT_DEVROOT:
+ case MIXT_GROUP:
+ case MIXT_MESSAGE:
+ case MIXT_MONOVU:
+ case MIXT_STEREOVU:
+ case MIXT_MONOPEAK:
+ case MIXT_STEREOPEAK:
+ case MIXT_MARKER:
+ continue; /* not interested in these types of controls */
+ case MIXT_MONODB:
+ case MIXT_STEREODB:
+ GST_DEBUG ("obsolete control type %d", mc->mixext.type);
+ continue;
+ case MIXT_MONOSLIDER:
+ case MIXT_STEREOSLIDER:
+ case MIXT_SLIDER:
+ case MIXT_MONOSLIDER16:
+ case MIXT_STEREOSLIDER16:
+ /* this shouldn't happen */
+ GST_ERROR ("unused slider control?!");
+ continue;
+ case MIXT_VALUE:
+ case MIXT_HEXVALUE:
+ /* value entry, not sure what to do with that, skip for now */
+ continue;
+ case MIXT_ONOFF:
+ case MIXT_MUTE:
+ case MIXT_ENUM:
+ case MIXT_3D:
+ case MIXT_RADIOGROUP:
+ GST_DEBUG ("FIXME: handle %s %s",
+ mixer_ext_type_get_name (mc->mixext.type), mc->mixext.extname);
+ break;
+ default:
+ GST_WARNING ("unknown control type %d", mc->mixext.type);
+ continue;
+ }
+ }
+}
+
+static GList *
+gst_oss4_mixer_create_tracks (GstOss4Mixer * mixer, const GList * controls)
+{
+ const GList *c;
+ GList *tracks = NULL;
+
+ for (c = controls; c != NULL; c = c->next) {
+ GstOss4MixerControl *mc = (GstOss4MixerControl *) c->data;
+ GstMixerTrack *track = NULL;
+
+ if (mc->is_virtual)
+ continue;
+
+ if (mc->is_slider) {
+ track = gst_oss4_mixer_slider_new (mixer, mc);
+ } else if (mc->is_enum) {
+ track = gst_oss4_mixer_enum_new (mixer, mc);
+ } else if (mc->is_switch) {
+ track = gst_oss4_mixer_switch_new (mixer, mc);
+ }
+
+ if (track == NULL)
+ continue;
+
+ track->label = gst_oss4_mixer_control_get_translated_name (mc);
+ track->flags = 0;
+
+ GST_LOG ("translated label: %s [%s] = %s", track->label, mc->mixext.id,
+ track->label);
+
+ /* This whole 'a track is either INPUT or OUTPUT' model is just flawed,
+ * esp. if a slider's role can be changed on the fly, like when you change
+ * function of a connector. What should we do in that case? Change the flag
+ * and make the app rebuild the interface? Ignore it? */
+ if (mc->mixext.flags & (MIXF_MAINVOL | MIXF_PCMVOL)) {
+ track->flags = GST_MIXER_TRACK_OUTPUT | GST_MIXER_TRACK_WHITELIST;
+
+ } else if (mc->mixext.flags & MIXF_RECVOL) {
+ /* record gain whitelisted by default */
+ track->flags = GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_NO_RECORD |
+ GST_MIXER_TRACK_WHITELIST;
+
+ } else if (mc->mixext.flags & MIXF_MONVOL) {
+ /* monitor sources not whitelisted by default */
+ track->flags = GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_NO_RECORD;
+ }
+
+ /*
+ * The kernel may give us better clues about the scope of a control.
+ * If so, try to honor it.
+ */
+ switch (mc->mixext.desc & MIXEXT_SCOPE_MASK) {
+ case MIXEXT_SCOPE_INPUT:
+ case MIXEXT_SCOPE_RECSWITCH:
+ track->flags |= GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_NO_RECORD |
+ GST_MIXER_TRACK_WHITELIST;
+ break;
+ case MIXEXT_SCOPE_MONITOR:
+ /* don't whitelist monitor tracks by default */
+ track->flags |= GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_NO_RECORD;
+ break;
+ case MIXEXT_SCOPE_OUTPUT:
+ track->flags = GST_MIXER_TRACK_OUTPUT | GST_MIXER_TRACK_WHITELIST;
+ break;
+ }
+
+ if (mc->is_master) {
+ track->flags |= GST_MIXER_TRACK_OUTPUT;
+ }
+
+ if (mc->is_master)
+ track->flags |= GST_MIXER_TRACK_MASTER;
+
+ tracks = g_list_append (tracks, track);
+ }
+
+ return tracks;
+}
+
+static void
+gst_oss4_mixer_update_tracks (GstOss4Mixer * mixer)
+{
+ GList *controls, *tracks;
+
+ /* read and process controls */
+ controls = gst_oss4_mixer_get_controls (mixer);
+
+ gst_oss4_mixer_controls_guess_master (mixer, controls);
+
+ gst_oss4_mixer_controls_find_sliders (mixer, controls);
+
+ gst_oss4_mixer_controls_find_enums (mixer, controls);
+
+ gst_oss4_mixer_controls_find_switches (mixer, controls);
+
+ gst_oss4_mixer_controls_find_virtual (mixer, controls);
+
+ gst_oss4_mixer_controls_dump_unused (mixer, controls);
+
+ tracks = gst_oss4_mixer_create_tracks (mixer, controls);
+
+ /* free old tracks and controls */
+ gst_oss4_mixer_free_tracks (mixer);
+
+ /* replace old with new */
+ mixer->tracks = tracks;
+ mixer->controls = controls;
+}
+
+static const GList *
+gst_oss4_mixer_list_tracks (GstMixer * mixer_iface)
+{
+ GstOss4Mixer *mixer = GST_OSS4_MIXER (mixer_iface);
+
+ g_return_val_if_fail (mixer != NULL, NULL);
+ g_return_val_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer), NULL);
+
+ GST_OBJECT_LOCK (mixer);
+
+ /* Do a read on the last control to check if the interface has changed */
+ if (!mixer->need_update && mixer->last_mixext.ctrl > 0) {
+ GstOss4MixerControl mc = { {0,}
+ ,
+ };
+ int val;
+
+ mc.mixext = mixer->last_mixext;
+ gst_oss4_mixer_get_control_val (mixer, &mc, &val);
+ }
+
+ if (mixer->need_update || mixer->tracks == NULL) {
+ gst_oss4_mixer_update_tracks (mixer);
+ mixer->need_update = FALSE;
+ }
+
+ GST_OBJECT_UNLOCK (mixer);
+
+ return (const GList *) mixer->tracks;
+}
+
+static void
+gst_oss4_mixer_set_volume (GstMixer * mixer, GstMixerTrack * track,
+ gint * volumes)
+{
+ GstOss4Mixer *oss;
+
+ g_return_if_fail (mixer != NULL);
+ g_return_if_fail (GST_IS_OSS4_MIXER (mixer));
+ g_return_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer));
+ g_return_if_fail (gst_oss4_mixer_contains_track (mixer, track));
+ g_return_if_fail (volumes != NULL);
+
+ oss = GST_OSS4_MIXER (mixer);
+
+ GST_OBJECT_LOCK (oss);
+
+ if (GST_IS_OSS4_MIXER_SLIDER (track)) {
+ gst_oss4_mixer_slider_set_volume (GST_OSS4_MIXER_SLIDER (track), volumes);
+ }
+
+ GST_OBJECT_UNLOCK (oss);
+}
+
+static void
+gst_oss4_mixer_get_volume (GstMixer * mixer, GstMixerTrack * track,
+ gint * volumes)
+{
+ GstOss4Mixer *oss;
+
+ g_return_if_fail (mixer != NULL);
+ g_return_if_fail (GST_IS_OSS4_MIXER (mixer));
+ g_return_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer));
+ g_return_if_fail (gst_oss4_mixer_contains_track (mixer, track));
+ g_return_if_fail (volumes != NULL);
+
+ oss = GST_OSS4_MIXER (mixer);
+
+ GST_OBJECT_LOCK (oss);
+
+ memset (volumes, 0, track->num_channels * sizeof (gint));
+
+ if (GST_IS_OSS4_MIXER_SWITCH (track)) {
+ gboolean enabled = FALSE;
+ gst_oss4_mixer_switch_get (GST_OSS4_MIXER_SWITCH (track), &enabled);
+ }
+ if (GST_IS_OSS4_MIXER_SLIDER (track)) {
+ gst_oss4_mixer_slider_get_volume (GST_OSS4_MIXER_SLIDER (track), volumes);
+ }
+
+ GST_OBJECT_UNLOCK (oss);
+}
+
+static void
+gst_oss4_mixer_set_record (GstMixer * mixer, GstMixerTrack * track,
+ gboolean record)
+{
+ GstOss4Mixer *oss;
+
+ g_return_if_fail (mixer != NULL);
+ g_return_if_fail (GST_IS_OSS4_MIXER (mixer));
+ g_return_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer));
+ g_return_if_fail (gst_oss4_mixer_contains_track (mixer, track));
+
+ oss = GST_OSS4_MIXER (mixer);
+
+ GST_OBJECT_LOCK (oss);
+
+ if (GST_IS_OSS4_MIXER_SLIDER (track)) {
+ gst_oss4_mixer_slider_set_record (GST_OSS4_MIXER_SLIDER (track), record);
+ } else if (GST_IS_OSS4_MIXER_SWITCH (track)) {
+ if ((track->flags & GST_MIXER_TRACK_INPUT)) {
+ gst_oss4_mixer_switch_set (GST_OSS4_MIXER_SWITCH (track), record);
+ } else {
+ GST_WARNING_OBJECT (track, "set_record called on non-INPUT track");
+ }
+ }
+
+ GST_OBJECT_UNLOCK (oss);
+}
+
+static void
+gst_oss4_mixer_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute)
+{
+ GstOss4Mixer *oss;
+
+ g_return_if_fail (mixer != NULL);
+ g_return_if_fail (GST_IS_OSS4_MIXER (mixer));
+ g_return_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer));
+ g_return_if_fail (gst_oss4_mixer_contains_track (mixer, track));
+
+ oss = GST_OSS4_MIXER (mixer);
+
+ GST_OBJECT_LOCK (oss);
+
+ if (GST_IS_OSS4_MIXER_SLIDER (track)) {
+ gst_oss4_mixer_slider_set_mute (GST_OSS4_MIXER_SLIDER (track), mute);
+ } else if (GST_IS_OSS4_MIXER_SWITCH (track)) {
+ gst_oss4_mixer_switch_set (GST_OSS4_MIXER_SWITCH (track), mute);
+ }
+
+ GST_OBJECT_UNLOCK (oss);
+}
+
+static void
+gst_oss4_mixer_set_option (GstMixer * mixer, GstMixerOptions * options,
+ gchar * value)
+{
+ GstOss4Mixer *oss;
+
+ g_return_if_fail (mixer != NULL);
+ g_return_if_fail (value != NULL);
+ g_return_if_fail (GST_IS_OSS4_MIXER (mixer));
+ g_return_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer));
+ g_return_if_fail (GST_IS_OSS4_MIXER_ENUM (options));
+ g_return_if_fail (gst_oss4_mixer_contains_options (mixer, options));
+
+ oss = GST_OSS4_MIXER (mixer);
+
+ GST_OBJECT_LOCK (oss);
+
+ if (!gst_oss4_mixer_enum_set_option (GST_OSS4_MIXER_ENUM (options), value)) {
+ /* not much we can do here but wake up the watch thread early, so it
+ * can do its thing and post messages if anything has changed */
+ gst_oss4_mixer_wake_up_watch_task (oss);
+ }
+
+ GST_OBJECT_UNLOCK (oss);
+}
+
+static const gchar *
+gst_oss4_mixer_get_option (GstMixer * mixer, GstMixerOptions * options)
+{
+ GstOss4Mixer *oss;
+ const gchar *current_val;
+
+ g_return_val_if_fail (mixer != NULL, NULL);
+ g_return_val_if_fail (GST_IS_OSS4_MIXER (mixer), NULL);
+ g_return_val_if_fail (GST_OSS4_MIXER_IS_OPEN (mixer), NULL);
+ g_return_val_if_fail (GST_IS_OSS4_MIXER_ENUM (options), NULL);
+ g_return_val_if_fail (gst_oss4_mixer_contains_options (mixer, options), NULL);
+
+ oss = GST_OSS4_MIXER (mixer);
+
+ GST_OBJECT_LOCK (oss);
+
+ current_val = gst_oss4_mixer_enum_get_option (GST_OSS4_MIXER_ENUM (options));
+
+ if (current_val == NULL) {
+ /* not much we can do here but wake up the watch thread early, so it
+ * can do its thing and post messages if anything has changed */
+ gst_oss4_mixer_wake_up_watch_task (oss);
+ }
+
+ GST_OBJECT_UNLOCK (oss);
+
+ return current_val;
+}
+
+static GstMixerFlags
+gst_oss4_mixer_get_mixer_flags (GstMixer * mixer)
+{
+ return GST_MIXER_FLAG_AUTO_NOTIFICATIONS | GST_MIXER_FLAG_HAS_WHITELIST |
+ GST_MIXER_FLAG_GROUPING;
+}
+
+static void
+gst_oss4_mixer_interface_init (GstMixerClass * klass)
+{
+ GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE;
+
+ klass->list_tracks = gst_oss4_mixer_list_tracks;
+ klass->set_volume = gst_oss4_mixer_set_volume;
+ klass->get_volume = gst_oss4_mixer_get_volume;
+ klass->set_mute = gst_oss4_mixer_set_mute;
+ klass->set_record = gst_oss4_mixer_set_record;
+ klass->set_option = gst_oss4_mixer_set_option;
+ klass->get_option = gst_oss4_mixer_get_option;
+ klass->get_mixer_flags = gst_oss4_mixer_get_mixer_flags;
+}
+
+/* Implement the horror that is GstImplementsInterface */
+
+static gboolean
+gst_oss4_mixer_supported (GstImplementsInterface * iface, GType iface_type)
+{
+ GstOss4Mixer *mixer;
+
+ g_return_val_if_fail (iface_type == GST_TYPE_MIXER, FALSE);
+
+ mixer = GST_OSS4_MIXER (iface);
+
+ return GST_OSS4_MIXER_IS_OPEN (mixer);
+}
+
+static void
+gst_oss4_mixer_implements_interface_init (GstImplementsInterfaceClass * klass)
+{
+ klass->supported = gst_oss4_mixer_supported;
+}
+
+static void
+gst_oss4_mixer_init_interfaces (GType type)
+{
+ static const GInterfaceInfo implements_iface_info = {
+ (GInterfaceInitFunc) gst_oss4_mixer_implements_interface_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo mixer_iface_info = {
+ (GInterfaceInitFunc) gst_oss4_mixer_interface_init,
+ NULL,
+ NULL,
+ };
+
+ g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
+ &implements_iface_info);
+ g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
+
+ gst_oss4_add_property_probe_interface (type);
+}
diff --git a/sys/oss4/oss4-mixer.h b/sys/oss4/oss4-mixer.h
new file mode 100644
index 0000000..4eaff50
--- /dev/null
+++ b/sys/oss4/oss4-mixer.h
@@ -0,0 +1,128 @@
+/* GStreamer OSS4 mixer implementation
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+
+#ifndef OSS4_MIXER_H
+#define OSS4_MIXER_H
+
+#include <gst/gst.h>
+
+#include "oss4-soundcard.h"
+
+#define GST_OSS4_MIXER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_MIXER,GstOss4Mixer))
+#define GST_OSS4_MIXER_CAST(obj) ((GstOss4Mixer *)(obj))
+#define GST_OSS4_MIXER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_MIXER,GstOss4MixerClass))
+#define GST_IS_OSS4_MIXER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_MIXER))
+#define GST_IS_OSS4_MIXER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_MIXER))
+#define GST_TYPE_OSS4_MIXER (gst_oss4_mixer_get_type())
+
+#define GST_OSS4_MIXER_IS_OPEN(obj) (GST_OSS4_MIXER(obj)->fd != -1)
+
+typedef struct _GstOss4Mixer GstOss4Mixer;
+typedef struct _GstOss4MixerClass GstOss4MixerClass;
+
+struct _GstOss4Mixer {
+ GstElement element;
+
+ /*< private >*/
+
+ /* element bits'n'bops */
+ gchar * device;
+
+ /* mixer details */
+ gint fd; /* file descriptor if open, or -1 */
+ gchar * device_name; /* device description, or NULL */
+ gchar * open_device; /* the device we opened */
+
+ GList * tracks; /* list of available tracks */
+ GList * controls; /* list of available controls */
+ gboolean need_update; /* re-read list of available tracks? */
+
+ oss_mixext last_mixext; /* we keep this around so we can
+ * easily check if the mixer
+ * interface has changed */
+
+ GThread * watch_thread; /* thread watching for value changes */
+ GCond * watch_cond;
+ gint watch_shutdown;
+ gint modify_counter; /* from MIXERINFO */
+
+ /* for property probe interface */
+ GList * property_probe_list;
+};
+
+struct _GstOss4MixerClass {
+ GstElementClass element_class;
+};
+
+/* helper struct holding info about one control */
+typedef struct _GstOss4MixerControl GstOss4MixerControl;
+
+struct _GstOss4MixerControl {
+ oss_mixext mixext;
+ GstOss4MixerControl *parent; /* NULL if root */
+ GstOss4MixerControl *mute; /* sibling with mute function, or NULL */
+ GList *mute_group; /* group of mute controls, or NULL */
+ GList *children; /* GstOss4MixerControls (no ownership) */
+
+ GQuark *enum_vals; /* 0-terminated array of values or NULL */
+ int enum_version; /* 0 = list won't change */
+
+ int last_val; /* last value seen */
+
+ gboolean is_virtual : 1; /* is a vmix control with dynamic label */
+ gboolean is_master : 1;
+ gboolean is_slider : 1; /* represent as slider */
+ gboolean is_switch : 1; /* represent as switch */
+ gboolean is_enum : 1; /* represent as combo/enumeration */
+ gboolean no_list : 1; /* enumeration with no list available */
+ gboolean is_input : 1; /* is an input-related control */
+ gboolean is_output : 1; /* is an output-related control */
+ gboolean used : 1; /* whether we know what to do with this */
+
+ gboolean changed : 1; /* transient flag used by watch thread */
+ gboolean list_changed : 1; /* transient flag used by watch thread */
+};
+
+/* header says parent=-1 means root, but it can also be parent=ctrl */
+#define MIXEXT_IS_ROOT(me) ((me).parent == -1 || (me).parent == (me).ctrl)
+
+#define MIXEXT_IS_SLIDER(me) ((me).type == MIXT_MONOSLIDER || \
+ (me).type == MIXT_STEREOSLIDER || (me).type == MIXT_MONOSLIDER16 || \
+ (me).type == MIXT_STEREOSLIDER16 || (me).type == MIXT_SLIDER)
+
+#define MIXEXT_HAS_DESCRIPTION(me) (((me).flags & MIXF_DESCR) != 0)
+
+#define MIXEXT_ENUM_IS_AVAILABLE(me,num) \
+ (((me).enum_present[num/8]) & (1 << (num % 8)))
+
+
+GType gst_oss4_mixer_get_type (void);
+
+gboolean gst_oss4_mixer_get_control_val (GstOss4Mixer * mixer,
+ GstOss4MixerControl * mc,
+ int * val);
+
+gboolean gst_oss4_mixer_set_control_val (GstOss4Mixer * mixer,
+ GstOss4MixerControl * mc,
+ int val);
+
+G_END_DECLS
+
+#endif /* OSS4_MIXER_H */
+
diff --git a/sys/oss4/oss4-property-probe.c b/sys/oss4/oss4-property-probe.c
new file mode 100644
index 0000000..a99410e
--- /dev/null
+++ b/sys/oss4/oss4-property-probe.c
@@ -0,0 +1,412 @@
+/* GStreamer OSS4 audio property probe interface implementation
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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 <gst/gst.h>
+
+#define NO_LEGACY_MIXER
+#include "oss4-audio.h"
+#include "oss4-mixer.h"
+#include "oss4-sink.h"
+#include "oss4-source.h"
+#include "oss4-soundcard.h"
+#include "oss4-property-probe.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+GST_DEBUG_CATEGORY_EXTERN (oss4_debug);
+#define GST_CAT_DEFAULT oss4_debug
+
+static const GList *
+gst_oss4_property_probe_get_properties (GstPropertyProbe * probe)
+{
+ GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
+ GList *list;
+
+ GST_OBJECT_LOCK (GST_OBJECT (probe));
+
+ /* we create a new list and store it in the instance struct, since apparently
+ * we forgot to update the API for 0.10 (and why don't we mark probable
+ * properties with a flag instead anyway?). A bit hackish, but what can you
+ * do (can't really use a static variable since the pspec will be different
+ * for src and sink class); this isn't particularly pretty, but the best
+ * we can do given that we can't create a common base class (we could do
+ * fancy things with the interface, or use g_object_set_data instead, but
+ * it's not really going to make it much better) */
+ if (GST_IS_AUDIO_SINK_CLASS (klass)) {
+ list = GST_OSS4_SINK (probe)->property_probe_list;
+ } else if (GST_IS_AUDIO_SRC_CLASS (klass)) {
+ list = GST_OSS4_SOURCE (probe)->property_probe_list;
+ } else if (GST_IS_OSS4_MIXER_CLASS (klass)) {
+ list = GST_OSS4_MIXER (probe)->property_probe_list;
+ } else {
+ GST_OBJECT_UNLOCK (GST_OBJECT (probe));
+ g_return_val_if_reached (NULL);
+ }
+
+ if (list == NULL) {
+ GParamSpec *pspec;
+
+ pspec = g_object_class_find_property (klass, "device");
+ list = g_list_prepend (NULL, pspec);
+
+ if (GST_IS_AUDIO_SINK_CLASS (klass)) {
+ GST_OSS4_SINK (probe)->property_probe_list = list;
+ } else if (GST_IS_AUDIO_SRC_CLASS (klass)) {
+ GST_OSS4_SOURCE (probe)->property_probe_list = list;
+ } else if (GST_IS_OSS4_MIXER_CLASS (klass)) {
+ GST_OSS4_MIXER (probe)->property_probe_list = list;
+ }
+ }
+
+ GST_OBJECT_UNLOCK (GST_OBJECT (probe));
+
+ return list;
+}
+
+static void
+gst_oss4_property_probe_probe_property (GstPropertyProbe * probe,
+ guint prop_id, const GParamSpec * pspec)
+{
+ if (!g_str_equal (pspec->name, "device")) {
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
+ }
+}
+
+static gboolean
+gst_oss4_property_probe_needs_probe (GstPropertyProbe * probe,
+ guint prop_id, const GParamSpec * pspec)
+{
+ /* don't cache probed data */
+ return TRUE;
+}
+
+static gint
+oss4_mixerinfo_priority_cmp (struct oss_mixerinfo *mi1,
+ struct oss_mixerinfo *mi2)
+{
+ /* return negative vaue if mi1 comes before mi2 */
+ if (mi1->priority != mi2->priority)
+ return mi2->priority - mi1->priority;
+
+ return strcmp (mi1->devnode, mi2->devnode);
+}
+
+/* caller must ensure LOCK is taken (e.g. if ioctls need to be serialised) */
+gboolean
+gst_oss4_property_probe_find_device_name (GstObject * obj, int fd,
+ const gchar * device_handle, gchar ** device_name)
+{
+ struct oss_sysinfo si = { {0,}, };
+ gchar *name = NULL;
+
+ if (ioctl (fd, SNDCTL_SYSINFO, &si) == 0) {
+ int i;
+
+ for (i = 0; i < si.numaudios; ++i) {
+ struct oss_audioinfo ai = { 0, };
+
+ ai.dev = i;
+ if (ioctl (fd, SNDCTL_AUDIOINFO, &ai) == -1) {
+ GST_DEBUG_OBJECT (obj, "AUDIOINFO ioctl for device %d failed", i);
+ continue;
+ }
+ if (strcmp (ai.devnode, device_handle) == 0) {
+ name = g_strdup (ai.name);
+ break;
+ }
+ }
+ } else {
+ GST_WARNING_OBJECT (obj, "SYSINFO ioctl failed: %s", g_strerror (errno));
+ }
+
+ /* try ENGINEINFO as fallback (which is better than nothing) */
+ if (name == NULL) {
+ struct oss_audioinfo ai = { 0, };
+
+ GST_LOG_OBJECT (obj, "device %s not listed in AUDIOINFO", device_handle);
+ ai.dev = -1;
+ if (ioctl (fd, SNDCTL_ENGINEINFO, &ai) == 0)
+ name = g_strdup (ai.name);
+ }
+
+ GST_DEBUG_OBJECT (obj, "Device name: %s", GST_STR_NULL (name));
+
+ if (name != NULL)
+ *device_name = name;
+
+ return (name != NULL);
+}
+
+gboolean
+gst_oss4_property_probe_find_device_name_nofd (GstObject * obj,
+ const gchar * device_handle, gchar ** device_name)
+{
+ gboolean res;
+ int fd;
+
+ fd = open ("/dev/mixer", O_RDONLY);
+ if (fd < 0)
+ return FALSE;
+
+ res = gst_oss4_property_probe_find_device_name (obj, fd, device_handle,
+ device_name);
+
+ close (fd);
+ return res;
+}
+
+static GList *
+gst_oss4_property_probe_get_mixer_devices (GstObject * obj, int fd,
+ struct oss_sysinfo *si)
+{
+ GList *m, *mixers = NULL;
+ GList *devices = NULL;
+
+ int i;
+
+ GST_LOG_OBJECT (obj, "%d mixer devices", si->nummixers);
+
+ /* first, find suitable mixer devices and sort by priority */
+ for (i = 0; i < si->nummixers; ++i) {
+ struct oss_mixerinfo mi = { 0, };
+
+ mi.dev = i;
+ if (ioctl (fd, SNDCTL_MIXERINFO, &mi) == -1) {
+ GST_DEBUG_OBJECT (obj, "MIXERINFO ioctl for device %d failed", i);
+ continue;
+ }
+
+ GST_INFO_OBJECT (obj, "mixer device %d:", i);
+ GST_INFO_OBJECT (obj, " enabled : %s", (mi.enabled) ? "yes" :
+ "no (powered off or unplugged)");
+ GST_INFO_OBJECT (obj, " priority : %d", mi.priority);
+ GST_INFO_OBJECT (obj, " devnode : %s", mi.devnode);
+ GST_INFO_OBJECT (obj, " handle : %s", mi.handle);
+ GST_INFO_OBJECT (obj, " caps : 0x%02x", mi.caps);
+ GST_INFO_OBJECT (obj, " name : %s", mi.name);
+
+ if (!mi.enabled) {
+ GST_DEBUG_OBJECT (obj, "mixer device is not usable/enabled, skipping");
+ continue;
+ }
+
+ /* only want mixers that control hardware directly */
+ if ((mi.caps & MIXER_CAP_VIRTUAL)) {
+ GST_DEBUG_OBJECT (obj, "mixer device is a virtual device, skipping");
+ continue;
+ }
+
+ mixers = g_list_insert_sorted (mixers, g_memdup (&mi, sizeof (mi)),
+ (GCompareFunc) oss4_mixerinfo_priority_cmp);
+ }
+
+ /* then create device list according to priority */
+ for (m = mixers; m != NULL; m = m->next) {
+ struct oss_mixerinfo *mi = (struct oss_mixerinfo *) m->data;
+
+ GST_LOG_OBJECT (obj, "mixer device: '%s'", mi->devnode);
+ devices = g_list_prepend (devices, g_strdup (mi->devnode));
+ g_free (m->data);
+ }
+ g_list_free (mixers);
+ mixers = NULL;
+
+ return g_list_reverse (devices);
+}
+
+static GList *
+gst_oss4_property_probe_get_audio_devices (GstObject * obj, int fd,
+ struct oss_sysinfo *si, int cap_mask)
+{
+ GList *devices = NULL;
+ int i;
+
+ GST_LOG_OBJECT (obj, "%d audio/dsp devices", si->numaudios);
+
+ for (i = 0; i < si->numaudios; ++i) {
+ struct oss_audioinfo ai = { 0, };
+
+ ai.dev = i;
+ if (ioctl (fd, SNDCTL_AUDIOINFO, &ai) == -1) {
+ GST_DEBUG_OBJECT (obj, "AUDIOINFO ioctl for device %d failed", i);
+ continue;
+ }
+
+ if ((ai.caps & cap_mask) == 0) {
+ GST_DEBUG_OBJECT (obj, "audio device %d is not an %s device", i,
+ (cap_mask == PCM_CAP_OUTPUT) ? "output" : "input");
+ continue;
+ }
+
+ if (!ai.enabled) {
+ GST_DEBUG_OBJECT (obj, "audio device %d is not usable/enabled", i);
+ continue;
+ }
+
+ GST_DEBUG_OBJECT (obj, "audio device %d looks ok: %s (\"%s\")", i,
+ ai.devnode, ai.name);
+
+ devices = g_list_prepend (devices, g_strdup (ai.devnode));
+ }
+
+ return g_list_reverse (devices);
+}
+
+static GValueArray *
+gst_oss4_property_probe_get_values (GstPropertyProbe * probe,
+ guint prop_id, const GParamSpec * pspec)
+{
+ struct oss_sysinfo si = { {0,}, };
+ GValueArray *array = NULL;
+ GstObject *obj;
+ GList *devices, *l;
+ int cap_mask, fd = -1;
+
+ if (!g_str_equal (pspec->name, "device")) {
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
+ return NULL;
+ }
+
+ obj = GST_OBJECT (probe);
+
+ GST_OBJECT_LOCK (obj);
+
+ /* figure out whether the element is a source or sink */
+ if (GST_IS_OSS4_SINK (probe)) {
+ GST_DEBUG_OBJECT (probe, "probing available output devices");
+ cap_mask = PCM_CAP_OUTPUT;
+ fd = GST_OSS4_SINK (probe)->fd;
+ } else if (GST_IS_OSS4_SOURCE (probe)) {
+ GST_DEBUG_OBJECT (probe, "probing available input devices");
+ cap_mask = PCM_CAP_INPUT;
+ fd = GST_OSS4_SOURCE (probe)->fd;
+ } else if (GST_IS_OSS4_MIXER (probe)) {
+ fd = GST_OSS4_MIXER (probe)->fd;
+ cap_mask = 0;
+ } else {
+ GST_OBJECT_UNLOCK (obj);
+ g_return_val_if_reached (NULL);
+ }
+
+ /* copy fd if it's open, so we can just unconditionally close() later */
+ if (fd != -1)
+ fd = dup (fd);
+
+ /* this will also catch the unlikely case where the above dup() failed */
+ if (fd == -1) {
+ fd = open ("/dev/mixer", O_RDONLY | O_NONBLOCK, 0);
+ if (fd < 0)
+ goto open_failed;
+ else if (!gst_oss4_audio_check_version (GST_OBJECT (probe), fd))
+ goto legacy_oss;
+ }
+
+ if (ioctl (fd, SNDCTL_SYSINFO, &si) == -1)
+ goto no_sysinfo;
+
+ if (cap_mask != 0) {
+ devices =
+ gst_oss4_property_probe_get_audio_devices (obj, fd, &si, cap_mask);
+ } else {
+ devices = gst_oss4_property_probe_get_mixer_devices (obj, fd, &si);
+ }
+
+ if (devices == NULL) {
+ GST_DEBUG_OBJECT (obj, "No devices found");
+ goto done;
+ }
+
+ array = g_value_array_new (1);
+
+ for (l = devices; l != NULL; l = l->next) {
+ GValue val = { 0, };
+
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_take_string (&val, (gchar *) l->data);
+ l->data = NULL;
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+ }
+
+ GST_OBJECT_UNLOCK (obj);
+
+ g_list_free (devices);
+
+done:
+
+ close (fd);
+
+ return array;
+
+/* ERRORS */
+open_failed:
+ {
+ GST_OBJECT_UNLOCK (GST_OBJECT (probe));
+ GST_WARNING_OBJECT (probe, "Can't open file descriptor to probe "
+ "available devices: %s", g_strerror (errno));
+ return NULL;
+ }
+legacy_oss:
+ {
+ close (fd);
+ GST_OBJECT_UNLOCK (GST_OBJECT (probe));
+ GST_DEBUG_OBJECT (probe, "Legacy OSS (ie. not OSSv4), not supported");
+ return NULL;
+ }
+no_sysinfo:
+ {
+ close (fd);
+ GST_OBJECT_UNLOCK (GST_OBJECT (probe));
+ GST_WARNING_OBJECT (probe, "Can't open file descriptor to probe "
+ "available devices: %s", g_strerror (errno));
+ return NULL;
+ }
+}
+
+static void
+gst_oss4_property_probe_interface_init (GstPropertyProbeInterface * iface)
+{
+ iface->get_properties = gst_oss4_property_probe_get_properties;
+ iface->probe_property = gst_oss4_property_probe_probe_property;
+ iface->needs_probe = gst_oss4_property_probe_needs_probe;
+ iface->get_values = gst_oss4_property_probe_get_values;
+}
+
+void
+gst_oss4_add_property_probe_interface (GType type)
+{
+ static const GInterfaceInfo probe_iface_info = {
+ (GInterfaceInitFunc) gst_oss4_property_probe_interface_init,
+ NULL,
+ NULL,
+ };
+
+ g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
+ &probe_iface_info);
+}
diff --git a/sys/oss4/oss4-property-probe.h b/sys/oss4/oss4-property-probe.h
new file mode 100644
index 0000000..707af02
--- /dev/null
+++ b/sys/oss4/oss4-property-probe.h
@@ -0,0 +1,38 @@
+/* GStreamer OSS4 audio property probe interface implementation
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+
+#ifndef GST_OSS4_PROPERTY_PROBE_H
+#define GST_OSS4_PROPERTY_PROBE_H
+
+#include <gst/interfaces/propertyprobe.h>
+
+void gst_oss4_add_property_probe_interface (GType type);
+
+gboolean gst_oss4_property_probe_find_device_name (GstObject * obj,
+ int fd,
+ const gchar * device_handle,
+ gchar ** device_name);
+
+gboolean gst_oss4_property_probe_find_device_name_nofd (GstObject * obj,
+ const gchar * device_handle,
+ gchar ** device_name);
+
+#endif /* GST_OSS4_PROPERTY_PROBE_H */
+
+
diff --git a/sys/oss4/oss4-sink.c b/sys/oss4/oss4-sink.c
new file mode 100644
index 0000000..54e95b9
--- /dev/null
+++ b/sys/oss4/oss4-sink.c
@@ -0,0 +1,696 @@
+/* GStreamer OSS4 audio sink
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+/**
+ * SECTION:element-oss4sink
+ *
+ * This element lets you output sound using the Open Sound System (OSS)
+ * version 4.
+ *
+ * Note that you should almost always use generic audio conversion elements
+ * like audioconvert and audioresample in front of an audiosink to make sure
+ * your pipeline works under all circumstances (those conversion elements will
+ * act in passthrough-mode if no conversion is necessary).
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * |[
+ * gst-launch -v audiotestsrc ! audioconvert ! volume volume=0.1 ! oss4sink
+ * ]| will output a sine wave (continuous beep sound) to your sound card (with
+ * a very low volume as precaution).
+ * |[
+ * gst-launch -v filesrc location=music.ogg ! decodebin ! audioconvert ! audioresample ! oss4sink
+ * ]| will play an Ogg/Vorbis audio file and output it using the Open Sound System
+ * version 4.
+ * </refsect2>
+ *
+ * Since: 0.10.7
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gst/gst-i18n-plugin.h>
+#include <gst/interfaces/streamvolume.h>
+
+#define NO_LEGACY_MIXER
+#include "oss4-audio.h"
+#include "oss4-sink.h"
+#include "oss4-property-probe.h"
+#include "oss4-soundcard.h"
+
+GST_DEBUG_CATEGORY_EXTERN (oss4sink_debug);
+#define GST_CAT_DEFAULT oss4sink_debug
+
+static void gst_oss4_sink_init_interfaces (GType type);
+static void gst_oss4_sink_dispose (GObject * object);
+static void gst_oss4_sink_finalize (GObject * object);
+
+static void gst_oss4_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static void gst_oss4_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+
+static GstCaps *gst_oss4_sink_getcaps (GstBaseSink * bsink);
+static gboolean gst_oss4_sink_open (GstAudioSink * asink,
+ gboolean silent_errors);
+static gboolean gst_oss4_sink_open_func (GstAudioSink * asink);
+static gboolean gst_oss4_sink_close (GstAudioSink * asink);
+static gboolean gst_oss4_sink_prepare (GstAudioSink * asink,
+ GstRingBufferSpec * spec);
+static gboolean gst_oss4_sink_unprepare (GstAudioSink * asink);
+static guint gst_oss4_sink_write (GstAudioSink * asink, gpointer data,
+ guint length);
+static guint gst_oss4_sink_delay (GstAudioSink * asink);
+static void gst_oss4_sink_reset (GstAudioSink * asink);
+
+#define DEFAULT_DEVICE NULL
+#define DEFAULT_DEVICE_NAME NULL
+#define DEFAULT_MUTE FALSE
+#define DEFAULT_VOLUME 1.0
+#define MAX_VOLUME 10.0
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+ PROP_DEVICE_NAME,
+ PROP_VOLUME,
+ PROP_MUTE,
+ PROP_LAST
+};
+
+GST_BOILERPLATE_FULL (GstOss4Sink, gst_oss4_sink, GstAudioSink,
+ GST_TYPE_AUDIO_SINK, gst_oss4_sink_init_interfaces);
+
+static void
+gst_oss4_sink_dispose (GObject * object)
+{
+ GstOss4Sink *osssink = GST_OSS4_SINK (object);
+
+ if (osssink->probed_caps) {
+ gst_caps_unref (osssink->probed_caps);
+ osssink->probed_caps = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_oss4_sink_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+ GstPadTemplate *templ;
+
+ gst_element_class_set_details_simple (element_class,
+ "OSS v4 Audio Sink", "Sink/Audio",
+ "Output to a sound card via OSS version 4",
+ "Tim-Philipp Müller <tim centricular net>");
+
+ templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+ gst_oss4_audio_get_template_caps ());
+ gst_element_class_add_pad_template (element_class, templ);
+ gst_object_unref (templ);
+}
+
+static void
+gst_oss4_sink_class_init (GstOss4SinkClass * klass)
+{
+ GstAudioSinkClass *audiosink_class = (GstAudioSinkClass *) klass;
+ GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass;
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+
+ gobject_class->dispose = gst_oss4_sink_dispose;
+ gobject_class->finalize = gst_oss4_sink_finalize;
+ gobject_class->get_property = gst_oss4_sink_get_property;
+ gobject_class->set_property = gst_oss4_sink_set_property;
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device",
+ "OSS4 device (e.g. /dev/oss/hdaudio0/pcm0 or /dev/dspN) "
+ "(NULL = use first available playback device)",
+ DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
+ g_param_spec_string ("device-name", "Device name",
+ "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class,
+ PROP_VOLUME,
+ g_param_spec_double ("volume", "Volume",
+ "Linear volume of this stream, 1.0=100%", 0.0, MAX_VOLUME,
+ DEFAULT_VOLUME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class,
+ PROP_MUTE,
+ g_param_spec_boolean ("mute", "Mute",
+ "Mute state of this stream", DEFAULT_MUTE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_oss4_sink_getcaps);
+
+ audiosink_class->open = GST_DEBUG_FUNCPTR (gst_oss4_sink_open_func);
+ audiosink_class->close = GST_DEBUG_FUNCPTR (gst_oss4_sink_close);
+ audiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_oss4_sink_prepare);
+ audiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_oss4_sink_unprepare);
+ audiosink_class->write = GST_DEBUG_FUNCPTR (gst_oss4_sink_write);
+ audiosink_class->delay = GST_DEBUG_FUNCPTR (gst_oss4_sink_delay);
+ audiosink_class->reset = GST_DEBUG_FUNCPTR (gst_oss4_sink_reset);
+}
+
+static void
+gst_oss4_sink_init (GstOss4Sink * osssink, GstOss4SinkClass * klass)
+{
+ const gchar *device;
+
+ device = g_getenv ("AUDIODEV");
+ if (device == NULL)
+ device = DEFAULT_DEVICE;
+ osssink->device = g_strdup (device);
+ osssink->fd = -1;
+ osssink->bytes_per_sample = 0;
+ osssink->probed_caps = NULL;
+ osssink->device_name = NULL;
+ osssink->mute_volume = 100 | (100 << 8);
+}
+
+static void
+gst_oss4_sink_finalize (GObject * object)
+{
+ GstOss4Sink *osssink = GST_OSS4_SINK (object);
+
+ g_free (osssink->device);
+ osssink->device = NULL;
+
+ g_list_free (osssink->property_probe_list);
+ osssink->property_probe_list = NULL;
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_oss4_sink_set_volume (GstOss4Sink * oss, gdouble volume)
+{
+ int ivol;
+
+ volume = volume * 100.0;
+ ivol = (int) volume | ((int) volume << 8);
+ GST_OBJECT_LOCK (oss);
+ if (ioctl (oss->fd, SNDCTL_DSP_SETPLAYVOL, &ivol) < 0) {
+ GST_LOG_OBJECT (oss, "SETPLAYVOL failed");
+ }
+ GST_OBJECT_UNLOCK (oss);
+}
+
+static gdouble
+gst_oss4_sink_get_volume (GstOss4Sink * oss)
+{
+ int ivol, lvol, rvol;
+ gdouble dvol = DEFAULT_VOLUME;
+
+ GST_OBJECT_LOCK (oss);
+ if (ioctl (oss->fd, SNDCTL_DSP_GETPLAYVOL, &ivol) < 0) {
+ GST_LOG_OBJECT (oss, "GETPLAYVOL failed");
+ } else {
+ /* Return the higher of the two volume channels, if different */
+ lvol = ivol & 0xff;
+ rvol = (ivol >> 8) & 0xff;
+ dvol = MAX (lvol, rvol) / 100.0;
+ }
+ GST_OBJECT_UNLOCK (oss);
+
+ return dvol;
+}
+
+static void
+gst_oss4_sink_set_mute (GstOss4Sink * oss, gboolean mute)
+{
+ int ivol;
+
+ if (mute) {
+ /*
+ * OSSv4 does not have a per-channel mute, so simulate by setting
+ * the value to 0. Save the volume before doing a mute so we can
+ * reset the value when the user un-mutes.
+ */
+ ivol = 0;
+
+ GST_OBJECT_LOCK (oss);
+ if (ioctl (oss->fd, SNDCTL_DSP_GETPLAYVOL, &oss->mute_volume) < 0) {
+ GST_LOG_OBJECT (oss, "GETPLAYVOL failed");
+ }
+ if (ioctl (oss->fd, SNDCTL_DSP_SETPLAYVOL, &ivol) < 0) {
+ GST_LOG_OBJECT (oss, "SETPLAYVOL failed");
+ }
+ GST_OBJECT_UNLOCK (oss);
+ } else {
+ /*
+ * If the saved volume is 0, then reset it to 100. Otherwise the mute
+ * can get stuck. This can happen, for example, due to rounding
+ * errors in converting from the float to an integer.
+ */
+ if (oss->mute_volume == 0) {
+ oss->mute_volume = 100 | (100 << 8);
+ }
+ GST_OBJECT_LOCK (oss);
+ if (ioctl (oss->fd, SNDCTL_DSP_SETPLAYVOL, &oss->mute_volume) < 0) {
+ GST_LOG_OBJECT (oss, "SETPLAYVOL failed");
+ }
+ GST_OBJECT_UNLOCK (oss);
+ }
+}
+
+static gboolean
+gst_oss4_sink_get_mute (GstOss4Sink * oss)
+{
+ int ivol, lvol, rvol;
+
+ GST_OBJECT_LOCK (oss);
+ if (ioctl (oss->fd, SNDCTL_DSP_GETPLAYVOL, &ivol) < 0) {
+ GST_LOG_OBJECT (oss, "GETPLAYVOL failed");
+ lvol = rvol = 100;
+ } else {
+ lvol = ivol & 0xff;
+ rvol = (ivol >> 8) & 0xff;
+ }
+ GST_OBJECT_UNLOCK (oss);
+
+ return (lvol == 0 && rvol == 0);
+}
+
+static void
+gst_oss4_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOss4Sink *oss = GST_OSS4_SINK (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ GST_OBJECT_LOCK (oss);
+ if (oss->fd == -1) {
+ g_free (oss->device);
+ oss->device = g_value_dup_string (value);
+ if (oss->probed_caps) {
+ gst_caps_unref (oss->probed_caps);
+ oss->probed_caps = NULL;
+ }
+ g_free (oss->device_name);
+ oss->device_name = NULL;
+ } else {
+ g_warning ("%s: can't change \"device\" property while audio sink "
+ "is open", GST_OBJECT_NAME (oss));
+ }
+ GST_OBJECT_UNLOCK (oss);
+ break;
+ case PROP_VOLUME:
+ gst_oss4_sink_set_volume (oss, g_value_get_double (value));
+ break;
+ case PROP_MUTE:
+ gst_oss4_sink_set_mute (oss, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_oss4_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstOss4Sink *oss = GST_OSS4_SINK (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ GST_OBJECT_LOCK (oss);
+ g_value_set_string (value, oss->device);
+ GST_OBJECT_UNLOCK (oss);
+ break;
+ case PROP_DEVICE_NAME:
+ GST_OBJECT_LOCK (oss);
+ if (oss->fd == -1 && oss->device != NULL) {
+ /* If device is set, try to retrieve the name even if we're not open */
+ if (gst_oss4_sink_open (GST_AUDIO_SINK (oss), TRUE)) {
+ g_value_set_string (value, oss->device_name);
+ gst_oss4_sink_close (GST_AUDIO_SINK (oss));
+ } else {
+ gchar *name = NULL;
+
+ gst_oss4_property_probe_find_device_name_nofd (GST_OBJECT (oss),
+ oss->device, &name);
+ g_value_set_string (value, name);
+ g_free (name);
+ }
+ } else {
+ g_value_set_string (value, oss->device_name);
+ }
+ GST_OBJECT_UNLOCK (oss);
+ break;
+ case PROP_VOLUME:
+ g_value_set_double (value, gst_oss4_sink_get_volume (oss));
+ break;
+ case PROP_MUTE:
+ g_value_set_boolean (value, gst_oss4_sink_get_mute (oss));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstCaps *
+gst_oss4_sink_getcaps (GstBaseSink * bsink)
+{
+ GstOss4Sink *oss;
+ GstCaps *caps;
+
+ oss = GST_OSS4_SINK (bsink);
+
+ if (oss->fd == -1) {
+ caps = gst_oss4_audio_get_template_caps ();
+ } else if (oss->probed_caps) {
+ caps = gst_caps_copy (oss->probed_caps);
+ } else {
+ caps = gst_oss4_audio_probe_caps (GST_OBJECT (oss), oss->fd);
+ if (caps != NULL && !gst_caps_is_empty (caps)) {
+ oss->probed_caps = gst_caps_copy (caps);
+ }
+ }
+
+ return caps;
+}
+
+/* note: we must not take the object lock here unless we fix up get_property */
+static gboolean
+gst_oss4_sink_open (GstAudioSink * asink, gboolean silent_errors)
+{
+ GstOss4Sink *oss;
+ gchar *device;
+ int mode;
+
+ oss = GST_OSS4_SINK (asink);
+
+ if (oss->device)
+ device = g_strdup (oss->device);
+ else
+ device = gst_oss4_audio_find_device (GST_OBJECT_CAST (oss));
+
+ /* desperate times, desperate measures */
+ if (device == NULL)
+ device = g_strdup ("/dev/dsp0");
+
+ GST_INFO_OBJECT (oss, "Trying to open OSS4 device '%s'", device);
+
+ /* we open in non-blocking mode even if we don't really want to do writes
+ * non-blocking because we can't be sure that this is really a genuine
+ * OSS4 device with well-behaved drivers etc. We really don't want to
+ * hang forever under any circumstances. */
+ oss->fd = open (device, O_WRONLY | O_NONBLOCK, 0);
+ if (oss->fd == -1) {
+ switch (errno) {
+ case EBUSY:
+ goto busy;
+ case EACCES:
+ goto no_permission;
+ default:
+ goto open_failed;
+ }
+ }
+
+ GST_INFO_OBJECT (oss, "Opened device '%s'", device);
+
+ /* Make sure it's OSS4. If it's old OSS, let osssink handle it */
+ if (!gst_oss4_audio_check_version (GST_OBJECT_CAST (oss), oss->fd))
+ goto legacy_oss;
+
+ /* now remove the non-blocking flag. */
+ mode = fcntl (oss->fd, F_GETFL);
+ mode &= ~O_NONBLOCK;
+ if (fcntl (oss->fd, F_SETFL, mode) < 0) {
+ /* some drivers do no support unsetting the non-blocking flag, try to
+ * close/open the device then. This is racy but we error out properly. */
+ GST_WARNING_OBJECT (oss, "failed to unset O_NONBLOCK (buggy driver?), "
+ "will try to re-open device now");
+ gst_oss4_sink_close (asink);
+ if ((oss->fd = open (device, O_WRONLY, 0)) == -1)
+ goto non_block;
+ }
+
+ oss->open_device = device;
+
+ /* not using ENGINEINFO here because it sometimes returns a different and
+ * less useful name than AUDIOINFO for the same device */
+ if (!gst_oss4_property_probe_find_device_name (GST_OBJECT (oss), oss->fd,
+ oss->open_device, &oss->device_name)) {
+ oss->device_name = NULL;
+ }
+
+ /* list output routings, for informational purposes only so far */
+ {
+ oss_mixer_enuminfo routings = { 0, };
+ guint i;
+
+ if (ioctl (oss->fd, SNDCTL_DSP_GET_PLAYTGT_NAMES, &routings) != -1) {
+ GST_LOG_OBJECT (oss, "%u output routings (static list: %d)",
+ routings.nvalues, !!(routings.version == 0));
+ for (i = 0; i < routings.nvalues; ++i) {
+ GST_LOG_OBJECT (oss, " output routing %d: %s", i,
+ &routings.strings[routings.strindex[i]]);
+ }
+ }
+ }
+
+ return TRUE;
+
+ /* ERRORS */
+busy:
+ {
+ if (!silent_errors) {
+ GST_ELEMENT_ERROR (oss, RESOURCE, BUSY,
+ (_("Could not open audio device for playback. "
+ "Device is being used by another application.")), (NULL));
+ }
+ g_free (device);
+ return FALSE;
+ }
+no_permission:
+ {
+ if (!silent_errors) {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
+ (_("Could not open audio device for playback. "
+ "You don't have permission to open the device.")),
+ GST_ERROR_SYSTEM);
+ }
+ g_free (device);
+ return FALSE;
+ }
+open_failed:
+ {
+ if (!silent_errors) {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
+ (_("Could not open audio device for playback.")), GST_ERROR_SYSTEM);
+ }
+ g_free (device);
+ return FALSE;
+ }
+legacy_oss:
+ {
+ if (!silent_errors) {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
+ (_("Could not open audio device for playback. "
+ "This version of the Open Sound System is not supported by this "
+ "element.")), ("Try the 'osssink' element instead"));
+ }
+ gst_oss4_sink_close (asink);
+ g_free (device);
+ return FALSE;
+ }
+non_block:
+ {
+ if (!silent_errors) {
+ GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, (NULL),
+ ("Unable to set device %s into non-blocking mode: %s",
+ oss->device, g_strerror (errno)));
+ }
+ g_free (device);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_oss4_sink_open_func (GstAudioSink * asink)
+{
+ return gst_oss4_sink_open (asink, FALSE);
+}
+
+static gboolean
+gst_oss4_sink_close (GstAudioSink * asink)
+{
+ GstOss4Sink *oss = GST_OSS4_SINK (asink);
+
+ if (oss->fd != -1) {
+ GST_DEBUG_OBJECT (oss, "closing device");
+ close (oss->fd);
+ oss->fd = -1;
+ }
+
+ oss->bytes_per_sample = 0;
+ /* we keep the probed caps cached, at least until the device changes */
+
+ g_free (oss->open_device);
+ oss->open_device = NULL;
+
+ g_free (oss->device_name);
+ oss->device_name = NULL;
+
+ if (oss->probed_caps) {
+ gst_caps_unref (oss->probed_caps);
+ oss->probed_caps = NULL;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_oss4_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
+{
+ GstOss4Sink *oss;
+
+ oss = GST_OSS4_SINK (asink);
+
+ if (!gst_oss4_audio_set_format (GST_OBJECT_CAST (oss), oss->fd, spec)) {
+ GST_WARNING_OBJECT (oss, "Couldn't set requested format %" GST_PTR_FORMAT,
+ spec->caps);
+ return FALSE;
+ }
+
+ oss->bytes_per_sample = spec->bytes_per_sample;
+ return TRUE;
+}
+
+static gboolean
+gst_oss4_sink_unprepare (GstAudioSink * asink)
+{
+ /* could do a SNDCTL_DSP_HALT, but the OSS manual recommends a close/open,
+ * since HALT won't properly reset some devices, apparently */
+
+ if (!gst_oss4_sink_close (asink))
+ goto couldnt_close;
+
+ if (!gst_oss4_sink_open_func (asink))
+ goto couldnt_reopen;
+
+ return TRUE;
+
+ /* ERRORS */
+couldnt_close:
+ {
+ GST_DEBUG_OBJECT (asink, "Couldn't close the audio device");
+ return FALSE;
+ }
+couldnt_reopen:
+ {
+ GST_DEBUG_OBJECT (asink, "Couldn't reopen the audio device");
+ return FALSE;
+ }
+}
+
+static guint
+gst_oss4_sink_write (GstAudioSink * asink, gpointer data, guint length)
+{
+ GstOss4Sink *oss;
+ int n;
+
+ oss = GST_OSS4_SINK_CAST (asink);
+
+ n = write (oss->fd, data, length);
+ GST_LOG_OBJECT (asink, "wrote %d/%d samples, %d bytes",
+ n / oss->bytes_per_sample, length / oss->bytes_per_sample, n);
+
+ if (G_UNLIKELY (n < 0)) {
+ switch (errno) {
+ case ENOTSUP:
+ case EACCES:{
+ /* This is the most likely cause, I think */
+ GST_ELEMENT_ERROR (asink, RESOURCE, WRITE,
+ (_("Playback is not supported by this audio device.")),
+ ("write: %s (device: %s) (maybe this is an input-only device?)",
+ g_strerror (errno), oss->open_device));
+ break;
+ }
+ default:{
+ GST_ELEMENT_ERROR (asink, RESOURCE, WRITE,
+ (_("Audio playback error.")),
+ ("write: %s (device: %s)", g_strerror (errno), oss->open_device));
+ break;
+ }
+ }
+ }
+
+ return n;
+}
+
+static guint
+gst_oss4_sink_delay (GstAudioSink * asink)
+{
+ GstOss4Sink *oss;
+ gint delay = -1;
+
+ oss = GST_OSS4_SINK_CAST (asink);
+
+ GST_OBJECT_LOCK (oss);
+ if (ioctl (oss->fd, SNDCTL_DSP_GETODELAY, &delay) < 0 || delay < 0) {
+ GST_LOG_OBJECT (oss, "GETODELAY failed");
+ }
+ GST_OBJECT_UNLOCK (oss);
+
+ if (G_UNLIKELY (delay < 0)) /* error case */
+ return 0;
+
+ return delay / oss->bytes_per_sample;
+}
+
+static void
+gst_oss4_sink_reset (GstAudioSink * asink)
+{
+ /* There's nothing we can do here really: OSS can't handle access to the
+ * same device/fd from multiple threads and might deadlock or blow up in
+ * other ways if we try an ioctl SNDCTL_DSP_HALT or similar */
+}
+
+static void
+gst_oss4_sink_init_interfaces (GType type)
+{
+ static const GInterfaceInfo svol_iface_info = {
+ NULL, NULL, NULL
+ };
+
+ g_type_add_interface_static (type, GST_TYPE_STREAM_VOLUME, &svol_iface_info);
+
+ gst_oss4_add_property_probe_interface (type);
+}
diff --git a/sys/oss4/oss4-sink.h b/sys/oss4/oss4-sink.h
new file mode 100644
index 0000000..b1489a7
--- /dev/null
+++ b/sys/oss4/oss4-sink.h
@@ -0,0 +1,64 @@
+/* GStreamer OSS4 audio sink
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+
+#ifndef GST_OSS4_SINK_H
+#define GST_OSS4_SINK_H
+
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosink.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSS4_SINK (gst_oss4_sink_get_type())
+#define GST_OSS4_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_SINK,GstOss4Sink))
+#define GST_OSS4_SINK_CAST(obj) ((GstOss4Sink *)(obj))
+#define GST_OSS4_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_SINK,GstOss4SinkClass))
+#define GST_IS_OSS4_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_SINK))
+#define GST_IS_OSS4_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_SINK))
+
+typedef struct _GstOss4Sink GstOss4Sink;
+typedef struct _GstOss4SinkClass GstOss4SinkClass;
+
+struct _GstOss4Sink {
+ GstAudioSink audio_sink;
+
+ gchar * device; /* NULL if none was set */
+ gchar * open_device; /* the device we opened */
+ gchar * device_name; /* set if the device is open */
+ gint fd; /* -1 if not open */
+ gint bytes_per_sample;
+ gint mute_volume;
+
+ GstCaps * probed_caps;
+
+ GList * property_probe_list;
+};
+
+struct _GstOss4SinkClass {
+ GstAudioSinkClass audio_sink_class;
+};
+
+GType gst_oss4_sink_get_type (void);
+
+G_END_DECLS
+
+#endif /* GST_OSS4_SINK_H */
+
+
diff --git a/sys/oss4/oss4-soundcard.h b/sys/oss4/oss4-soundcard.h
new file mode 100644
index 0000000..8b12489
--- /dev/null
+++ b/sys/oss4/oss4-soundcard.h
@@ -0,0 +1,2067 @@
+/*
+ * Purpose: The C/C++ header file that defines the OSS API.
+ * Description:
+ * This header file contains all the declarations required to compile OSS
+ * programs. The latest version is always installed together with OSS
+ * use of the latest version is strongly recommended.
+ *
+ * {!notice This header file contains many obsolete definitions
+ * (for compatibility with older applications that still ned them).
+ * Do not use this file as a reference manual of OSS.
+ * Please check the OSS Programmer's guide for descriptions
+ * of the supported API details (http://manuals.opensound.com/developer).}
+ */
+
+#ifndef SOUNDCARD_H
+#define SOUNDCARD_H
+
+#define COPYING40 Copyright (C) 4Front Technologies 2000-2006. Released under the BSD license.
+
+#if defined(__cplusplus)
+#define EXTERNC extern "C"
+#else
+#define EXTERNC extern
+#endif /* EXTERN_C_WRAPPERS */
+
+#define OSS_VERSION 0x040090 // Pre 4.1
+
+#define SOUND_VERSION OSS_VERSION
+#define OPEN_SOUND_SYSTEM
+
+#if defined(__hpux) && !defined(_HPUX_SOURCE)
+# error "-D_HPUX_SOURCE must be used when compiling OSS applications"
+#endif
+
+#ifdef __hpux
+#include <sys/ioctl.h>
+#endif
+
+#ifdef linux
+/* In Linux we need to be prepared for cross compiling */
+#include <linux/ioctl.h>
+#else
+# ifdef __FreeBSD__
+# include <sys/ioccom.h>
+# else
+# include <sys/ioctl.h>
+# endif
+#endif
+
+#ifndef __SIOWR
+#if defined(__hpux) || (defined(_IOWR) && (defined(_AIX) || (!defined(sun) && !defined(sparc) && !defined(__INCioctlh) && !defined(__Lynx__))))
+
+/*
+ * Make sure the ioctl macros are compatible with the ones already used
+ * by this operating system.
+ */
+#define SIOCPARM_MASK IOCPARM_MASK
+#define SIOC_VOID IOC_VOID
+#define SIOC_OUT IOC_OUT
+#define SIOC_IN IOC_IN
+#define SIOC_INOUT IOC_INOUT
+#define __SIOC_SIZE _IOC_SIZE
+#define __SIOC_DIR _IOC_DIR
+#define __SIOC_NONE _IOC_NONE
+#define __SIOC_READ _IOC_READ
+#define __SIOC_WRITE _IOC_WRITE
+#define __SIO _IO
+#define __SIOR _IOR
+#define __SIOW _IOW
+#define __SIOWR _IOWR
+#else
+
+/* #define SIOCTYPE (0xff<<8) */
+#define SIOCPARM_MASK 0x1fff /* parameters must be < 8192 bytes */
+#define SIOC_VOID 0x00000000 /* no parameters */
+#define SIOC_OUT 0x20000000 /* copy out parameters */
+#define SIOC_IN 0x40000000 /* copy in parameters */
+#define SIOC_INOUT (SIOC_IN|SIOC_OUT)
+
+#define __SIO(x,y) ((int)(SIOC_VOID|(x<<8)|y))
+#define __SIOR(x,y,t) ((int)(SIOC_OUT|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y))
+#define __SIOW(x,y,t) ((int)(SIOC_IN|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y))
+#define __SIOWR(x,y,t) ((int)(SIOC_INOUT|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y))
+#define __SIOC_SIZE(x) ((x>>16)&SIOCPARM_MASK)
+#define __SIOC_DIR(x) (x & 0xf0000000)
+#define __SIOC_NONE SIOC_VOID
+#define __SIOC_READ SIOC_OUT
+#define __SIOC_WRITE SIOC_IN
+# endif /* _IOWR */
+#endif /* !__SIOWR */
+
+#define OSS_LONGNAME_SIZE 64
+#define OSS_LABEL_SIZE 16
+#define OSS_DEVNODE_SIZE 32
+typedef char oss_longname_t[OSS_LONGNAME_SIZE];
+typedef char oss_label_t[OSS_LABEL_SIZE];
+typedef char oss_devnode_t[OSS_DEVNODE_SIZE];
+
+#ifndef DISABLE_SEQUENCER
+/*
+ ****************************************************************************
+ * IOCTL Commands for /dev/sequencer and /dev/music (AKA /dev/sequencer2)
+ *
+ * Note that this interface is obsolete and no longer developed. New
+ * applications should use /dev/midi instead.
+ ****************************************************************************/
+#define SNDCTL_SEQ_RESET __SIO ('Q', 0)
+#define SNDCTL_SEQ_SYNC __SIO ('Q', 1)
+#define SNDCTL_SYNTH_INFO __SIOWR('Q', 2, struct synth_info)
+#define SNDCTL_SEQ_CTRLRATE __SIOWR('Q', 3, int) /* Set/get timer resolution (HZ) */
+#define SNDCTL_SEQ_GETOUTCOUNT __SIOR ('Q', 4, int)
+#define SNDCTL_SEQ_GETINCOUNT __SIOR ('Q', 5, int)
+#define SNDCTL_SEQ_PERCMODE __SIOW ('Q', 6, int)
+#define SNDCTL_FM_LOAD_INSTR __SIOW ('Q', 7, struct sbi_instrument) /* Obsolete. Don't use!!!!!! */
+#define SNDCTL_SEQ_TESTMIDI __SIOW ('Q', 8, int)
+#define SNDCTL_SEQ_RESETSAMPLES __SIOW ('Q', 9, int)
+#define SNDCTL_SEQ_NRSYNTHS __SIOR ('Q',10, int)
+#define SNDCTL_SEQ_NRMIDIS __SIOR ('Q',11, int)
+#define SNDCTL_MIDI_INFO __SIOWR('Q',12, struct midi_info) /* OBSOLETE - use SNDCTL_MIDIINFO instead */
+#define SNDCTL_SEQ_THRESHOLD __SIOW ('Q',13, int)
+#define SNDCTL_SYNTH_MEMAVL __SIOWR('Q',14, int) /* in=dev#, out=memsize */
+#define SNDCTL_FM_4OP_ENABLE __SIOW ('Q',15, int) /* in=dev# */
+#define SNDCTL_SEQ_PANIC __SIO ('Q',17)
+#define SNDCTL_SEQ_OUTOFBAND __SIOW ('Q',18, struct seq_event_rec)
+#define SNDCTL_SEQ_GETTIME __SIOR ('Q',19, int)
+#define SNDCTL_SYNTH_ID __SIOWR('Q',20, struct synth_info)
+#define SNDCTL_SYNTH_CONTROL __SIOWR('Q',21, struct synth_control)
+#define SNDCTL_SYNTH_REMOVESAMPLE __SIOWR('Q',22, struct remove_sample) /* Reserved for future use */
+#define SNDCTL_SEQ_TIMING_ENABLE __SIO ('Q', 23) /* Enable incoming MIDI timing messages */
+#define SNDCTL_SEQ_ACTSENSE_ENABLE __SIO ('Q', 24) /* Enable incoming active sensing messages */
+#define SNDCTL_SEQ_RT_ENABLE __SIO ('Q', 25) /* Enable other incoming realtime messages */
+
+typedef struct synth_control
+{
+ int devno; /* Synthesizer # */
+ char data[4000]; /* Device spesific command/data record */
+} synth_control;
+
+typedef struct remove_sample
+{
+ int devno; /* Synthesizer # */
+ int bankno; /* MIDI bank # (0=General MIDI) */
+ int instrno; /* MIDI instrument number */
+} remove_sample;
+
+typedef struct seq_event_rec
+{
+ unsigned char arr[8];
+} seq_event_rec;
+
+#define SNDCTL_TMR_TIMEBASE __SIOWR('T', 1, int)
+#define SNDCTL_TMR_START __SIO ('T', 2)
+#define SNDCTL_TMR_STOP __SIO ('T', 3)
+#define SNDCTL_TMR_CONTINUE __SIO ('T', 4)
+#define SNDCTL_TMR_TEMPO __SIOWR('T', 5, int)
+#define SNDCTL_TMR_SOURCE __SIOWR('T', 6, int)
+# define TMR_INTERNAL 0x00000001
+# define TMR_EXTERNAL 0x00000002
+# define TMR_MODE_MIDI 0x00000010
+# define TMR_MODE_FSK 0x00000020
+# define TMR_MODE_CLS 0x00000040
+# define TMR_MODE_SMPTE 0x00000080
+#define SNDCTL_TMR_METRONOME __SIOW ('T', 7, int)
+#define SNDCTL_TMR_SELECT __SIOW ('T', 8, int)
+
+/*
+ * Sample loading mechanism for internal synthesizers (/dev/sequencer)
+ * (for the .PAT format).
+ */
+
+struct patch_info
+{
+ unsigned short key; /* Use WAVE_PATCH here */
+#define WAVE_PATCH _PATCHKEY(0x04)
+#define GUS_PATCH WAVE_PATCH
+#define WAVEFRONT_PATCH _PATCHKEY(0x06)
+
+ short device_no; /* Synthesizer number */
+ short instr_no; /* Midi pgm# */
+
+ unsigned int mode;
+/*
+ * The least significant byte has the same format than the GUS .PAT
+ * files
+ */
+#define WAVE_16_BITS 0x01 /* bit 0 = 8 or 16 bit wave data. */
+#define WAVE_UNSIGNED 0x02 /* bit 1 = Signed - Unsigned data. */
+#define WAVE_LOOPING 0x04 /* bit 2 = looping enabled-1. */
+#define WAVE_BIDIR_LOOP 0x08 /* bit 3 = Set is bidirectional looping. */
+#define WAVE_LOOP_BACK 0x10 /* bit 4 = Set is looping backward. */
+#define WAVE_SUSTAIN_ON 0x20 /* bit 5 = Turn sustaining on. (Env. pts. 3) */
+#define WAVE_ENVELOPES 0x40 /* bit 6 = Enable envelopes - 1 */
+#define WAVE_FAST_RELEASE 0x80 /* bit 7 = Shut off immediately after note off */
+ /* (use the env_rate/env_offs fields). */
+/* Linux specific bits */
+#define WAVE_VIBRATO 0x00010000 /* The vibrato info is valid */
+#define WAVE_TREMOLO 0x00020000 /* The tremolo info is valid */
+#define WAVE_SCALE 0x00040000 /* The scaling info is valid */
+#define WAVE_FRACTIONS 0x00080000 /* Fraction information is valid */
+/* Reserved bits */
+#define WAVE_ROM 0x40000000 /* For future use */
+#define WAVE_MULAW 0x20000000 /* For future use */
+/* Other bits must be zeroed */
+
+ int len; /* Size of the wave data in bytes */
+ int loop_start, loop_end; /* Byte offsets from the beginning */
+
+/*
+ * The base_freq and base_note fields are used when computing the
+ * playback speed for a note. The base_note defines the tone frequency
+ * which is heard if the sample is played using the base_freq as the
+ * playback speed.
+ *
+ * The low_note and high_note fields define the minimum and maximum note
+ * frequencies for which this sample is valid. It is possible to define
+ * more than one samples for an instrument number at the same time. The
+ * low_note and high_note fields are used to select the most suitable one.
+ *
+ * The fields base_note, high_note and low_note should contain
+ * the note frequency multiplied by 1000. For example value for the
+ * middle A is 440*1000.
+ */
+
+ unsigned int base_freq;
+ unsigned int base_note;
+ unsigned int high_note;
+ unsigned int low_note;
+ int panning; /* -128=left, 127=right */
+ int detuning;
+
+ /* Envelope. Enabled by mode bit WAVE_ENVELOPES */
+ unsigned char env_rate[6]; /* GUS HW ramping rate */
+ unsigned char env_offset[6]; /* 255 == 100% */
+
+ /*
+ * The tremolo, vibrato and scale info are not supported yet.
+ * Enable by setting the mode bits WAVE_TREMOLO, WAVE_VIBRATO or
+ * WAVE_SCALE
+ */
+
+ unsigned char tremolo_sweep;
+ unsigned char tremolo_rate;
+ unsigned char tremolo_depth;
+
+ unsigned char vibrato_sweep;
+ unsigned char vibrato_rate;
+ unsigned char vibrato_depth;
+
+ int scale_frequency;
+ unsigned int scale_factor; /* from 0 to 2048 or 0 to 2 */
+
+ int volume;
+ int fractions;
+ int reserved1;
+ int spare[2];
+ char data[1]; /* The waveform data starts here */
+};
+
+struct sysex_info
+{
+ short key; /* Use SYSEX_PATCH or MAUI_PATCH here */
+#define SYSEX_PATCH _PATCHKEY(0x05)
+#define MAUI_PATCH _PATCHKEY(0x06)
+ short device_no; /* Synthesizer number */
+ int len; /* Size of the sysex data in bytes */
+ unsigned char data[1]; /* Sysex data starts here */
+};
+
+/*
+ * /dev/sequencer input events.
+ *
+ * The data written to the /dev/sequencer is a stream of events. Events
+ * are records of 4 or 8 bytes. The first byte defines the size.
+ * Any number of events can be written with a write call. There
+ * is a set of macros for sending these events. Use these macros if you
+ * want to maximize portability of your program.
+ *
+ * Events SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO. Are also input events.
+ * (All input events are currently 4 bytes long. Be prepared to support
+ * 8 byte events also. If you receive any event having first byte >= 128,
+ * it's a 8 byte event.
+ *
+ * The events are documented at the end of this file.
+ *
+ * Normal events (4 bytes)
+ * There is also a 8 byte version of most of the 4 byte events. The
+ * 8 byte one is recommended.
+ *
+ * NOTE! All 4 byte events are now obsolete. Applications should not write
+ * them. However 4 byte events are still used as inputs from
+ * /dev/sequencer (/dev/music uses only 8 byte ones).
+ */
+#define SEQ_NOTEOFF 0
+#define SEQ_FMNOTEOFF SEQ_NOTEOFF /* Just old name */
+#define SEQ_NOTEON 1
+#define SEQ_FMNOTEON SEQ_NOTEON
+#define SEQ_WAIT TMR_WAIT_ABS
+#define SEQ_PGMCHANGE 3
+#define SEQ_FMPGMCHANGE SEQ_PGMCHANGE
+#define SEQ_SYNCTIMER TMR_START
+#define SEQ_MIDIPUTC 5
+#define SEQ_DRUMON 6 /*** OBSOLETE ***/
+#define SEQ_DRUMOFF 7 /*** OBSOLETE ***/
+#define SEQ_ECHO TMR_ECHO /* For synching programs with output */
+#define SEQ_AFTERTOUCH 9
+#define SEQ_CONTROLLER 10
+#define SEQ_BALANCE 11
+#define SEQ_VOLMODE 12
+
+/************************************
+ * Midi controller numbers *
+ ************************************/
+/*
+ * Controllers 0 to 31 (0x00 to 0x1f) and
+ * 32 to 63 (0x20 to 0x3f) are continuous
+ * controllers.
+ * In the MIDI 1.0 these controllers are sent using
+ * two messages. Controller numbers 0 to 31 are used
+ * to send the MSB and the controller numbers 32 to 63
+ * are for the LSB. Note that just 7 bits are used in MIDI bytes.
+ */
+
+#define CTL_BANK_SELECT 0x00
+#define CTL_MODWHEEL 0x01
+#define CTL_BREATH 0x02
+/* undefined 0x03 */
+#define CTL_FOOT 0x04
+#define CTL_PORTAMENTO_TIME 0x05
+#define CTL_DATA_ENTRY 0x06
+#define CTL_MAIN_VOLUME 0x07
+#define CTL_BALANCE 0x08
+/* undefined 0x09 */
+#define CTL_PAN 0x0a
+#define CTL_EXPRESSION 0x0b
+/* undefined 0x0c */
+/* undefined 0x0d */
+/* undefined 0x0e */
+/* undefined 0x0f */
+#define CTL_GENERAL_PURPOSE1 0x10
+#define CTL_GENERAL_PURPOSE2 0x11
+#define CTL_GENERAL_PURPOSE3 0x12
+#define CTL_GENERAL_PURPOSE4 0x13
+/* undefined 0x14 - 0x1f */
+
+/* undefined 0x20 */
+/* The controller numbers 0x21 to 0x3f are reserved for the */
+/* least significant bytes of the controllers 0x00 to 0x1f. */
+/* These controllers are not recognised by the driver. */
+
+/* Controllers 64 to 69 (0x40 to 0x45) are on/off switches. */
+/* 0=OFF and 127=ON (intermediate values are possible) */
+#define CTL_DAMPER_PEDAL 0x40
+#define CTL_SUSTAIN 0x40 /* Alias */
+#define CTL_HOLD 0x40 /* Alias */
+#define CTL_PORTAMENTO 0x41
+#define CTL_SOSTENUTO 0x42
+#define CTL_SOFT_PEDAL 0x43
+/* undefined 0x44 */
+#define CTL_HOLD2 0x45
+/* undefined 0x46 - 0x4f */
+
+#define CTL_GENERAL_PURPOSE5 0x50
+#define CTL_GENERAL_PURPOSE6 0x51
+#define CTL_GENERAL_PURPOSE7 0x52
+#define CTL_GENERAL_PURPOSE8 0x53
+/* undefined 0x54 - 0x5a */
+#define CTL_EXT_EFF_DEPTH 0x5b
+#define CTL_TREMOLO_DEPTH 0x5c
+#define CTL_CHORUS_DEPTH 0x5d
+#define CTL_DETUNE_DEPTH 0x5e
+#define CTL_CELESTE_DEPTH 0x5e /* Alias for the above one */
+#define CTL_PHASER_DEPTH 0x5f
+#define CTL_DATA_INCREMENT 0x60
+#define CTL_DATA_DECREMENT 0x61
+#define CTL_NONREG_PARM_NUM_LSB 0x62
+#define CTL_NONREG_PARM_NUM_MSB 0x63
+#define CTL_REGIST_PARM_NUM_LSB 0x64
+#define CTL_REGIST_PARM_NUM_MSB 0x65
+/* undefined 0x66 - 0x78 */
+/* reserved 0x79 - 0x7f */
+
+/* Pseudo controllers (not midi compatible) */
+#define CTRL_PITCH_BENDER 255
+#define CTRL_PITCH_BENDER_RANGE 254
+#define CTRL_EXPRESSION 253 /* Obsolete */
+#define CTRL_MAIN_VOLUME 252 /* Obsolete */
+
+/*
+ * Volume mode defines how volumes are used
+ */
+
+#define VOL_METHOD_ADAGIO 1
+#define VOL_METHOD_LINEAR 2
+
+/*
+ * Note! SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO are used also as
+ * input events.
+ */
+
+/*
+ * Event codes 0xf0 to 0xfc are reserved for future extensions.
+ */
+
+#define SEQ_FULLSIZE 0xfd /* Long events */
+/*
+ * SEQ_FULLSIZE events are used for loading patches/samples to the
+ * synthesizer devices. These events are passed directly to the driver
+ * of the associated synthesizer device. There is no limit to the size
+ * of the extended events. These events are not queued but executed
+ * immediately when the write() is called (execution can take several
+ * seconds of time).
+ *
+ * When a SEQ_FULLSIZE message is written to the device, it must
+ * be written using exactly one write() call. Other events cannot
+ * be mixed to the same write.
+ *
+ * For FM synths (YM3812/OPL3) use struct sbi_instrument and write it to the
+ * /dev/sequencer. Don't write other data together with the instrument structure
+ * Set the key field of the structure to FM_PATCH. The device field is used to
+ * route the patch to the corresponding device.
+ *
+ * For wave table use struct patch_info. Initialize the key field
+ * to WAVE_PATCH.
+ */
+#define SEQ_PRIVATE 0xfe /* Low level HW dependent events (8 bytes) */
+#define SEQ_EXTENDED 0xff /* Extended events (8 bytes) OBSOLETE */
+
+/*
+ * Record for FM patches
+ */
+
+typedef unsigned char sbi_instr_data[32];
+
+struct sbi_instrument
+{
+ unsigned short key; /* FM_PATCH or OPL3_PATCH */
+#define FM_PATCH _PATCHKEY(0x01)
+#define OPL3_PATCH _PATCHKEY(0x03)
+ short device; /* Synth# (0-4) */
+ int channel; /* Program# to be initialized */
+ sbi_instr_data operators; /* Register settings for operator cells (.SBI format) */
+};
+
+struct synth_info
+{ /* Read only */
+ char name[30];
+ int device; /* 0-N. INITIALIZE BEFORE CALLING */
+ int synth_type;
+#define SYNTH_TYPE_FM 0
+#define SYNTH_TYPE_SAMPLE 1
+#define SYNTH_TYPE_MIDI 2 /* Midi interface */
+
+ int synth_subtype;
+#define FM_TYPE_ADLIB 0x00
+#define FM_TYPE_OPL3 0x01
+#define MIDI_TYPE_MPU401 0x401
+
+#define SAMPLE_TYPE_BASIC 0x10
+#define SAMPLE_TYPE_GUS SAMPLE_TYPE_BASIC
+#define SAMPLE_TYPE_WAVEFRONT 0x11
+
+ int perc_mode; /* No longer supported */
+ int nr_voices;
+ int nr_drums; /* Obsolete field */
+ int instr_bank_size;
+ unsigned int capabilities;
+#define SYNTH_CAP_PERCMODE 0x00000001 /* No longer used */
+#define SYNTH_CAP_OPL3 0x00000002 /* Set if OPL3 supported */
+#define SYNTH_CAP_INPUT 0x00000004 /* Input (MIDI) device */
+ int dummies[19]; /* Reserve space */
+};
+
+struct sound_timer_info
+{
+ char name[32];
+ int caps;
+};
+
+struct midi_info /* OBSOLETE */
+{
+ char name[30];
+ int device; /* 0-N. INITIALIZE BEFORE CALLING */
+ unsigned int capabilities; /* To be defined later */
+ int dev_type;
+ int dummies[18]; /* Reserve space */
+};
+
+/*
+ * Level 2 event types for /dev/sequencer
+ */
+
+/*
+ * The 4 most significant bits of byte 0 specify the class of
+ * the event:
+ *
+ * 0x8X = system level events,
+ * 0x9X = device/port specific events, event[1] = device/port,
+ * The last 4 bits give the subtype:
+ * 0x02 = Channel event (event[3] = chn).
+ * 0x01 = note event (event[4] = note).
+ * (0x01 is not used alone but always with bit 0x02).
+ * event[2] = MIDI message code (0x80=note off etc.)
+ *
+ */
+
+#define EV_SEQ_LOCAL 0x80
+#define EV_TIMING 0x81
+#define EV_CHN_COMMON 0x92
+#define EV_CHN_VOICE 0x93
+#define EV_SYSEX 0x94
+#define EV_SYSTEM 0x95 /* MIDI system and real time messages (input only) */
+/*
+ * Event types 200 to 220 are reserved for application use.
+ * These numbers will not be used by the driver.
+ */
+
+/*
+ * Events for event type EV_CHN_VOICE
+ */
+
+#define MIDI_NOTEOFF 0x80
+#define MIDI_NOTEON 0x90
+#define MIDI_KEY_PRESSURE 0xA0
+
+/*
+ * Events for event type EV_CHN_COMMON
+ */
+
+#define MIDI_CTL_CHANGE 0xB0
+#define MIDI_PGM_CHANGE 0xC0
+#define MIDI_CHN_PRESSURE 0xD0
+#define MIDI_PITCH_BEND 0xE0
+
+#define MIDI_SYSTEM_PREFIX 0xF0
+
+/*
+ * Timer event types
+ */
+#define TMR_WAIT_REL 1 /* Time relative to the prev time */
+#define TMR_WAIT_ABS 2 /* Absolute time since TMR_START */
+#define TMR_STOP 3
+#define TMR_START 4
+#define TMR_CONTINUE 5
+#define TMR_TEMPO 6
+#define TMR_ECHO 8
+#define TMR_CLOCK 9 /* MIDI clock */
+#define TMR_SPP 10 /* Song position pointer */
+#define TMR_TIMESIG 11 /* Time signature */
+
+/*
+ * Local event types
+ */
+#define LOCL_STARTAUDIO 1
+#define LOCL_STARTAUDIO2 2
+#define LOCL_STARTAUDIO3 3
+#define LOCL_STARTAUDIO4 4
+
+#if (!defined(__KERNEL__) && !defined(KERNEL) && !defined(INKERNEL) && !defined(_KERNEL)) || defined(USE_SEQ_MACROS)
+/*
+ * Some convenience macros to simplify programming of the
+ * /dev/sequencer interface
+ *
+ * These macros define the API which should be used when possible.
+ */
+#define SEQ_DECLAREBUF() SEQ_USE_EXTBUF()
+
+void seqbuf_dump (void); /* This function must be provided by programs */
+
+EXTERNC int OSS_init (int seqfd, int buflen);
+EXTERNC void OSS_seqbuf_dump (int fd, unsigned char *buf, int buflen);
+EXTERNC void OSS_seq_advbuf (int len, int fd, unsigned char *buf, int buflen);
+EXTERNC void OSS_seq_needbuf (int len, int fd, unsigned char *buf,
+ int buflen);
+EXTERNC void OSS_patch_caching (int dev, int chn, int patch, int fd,
+ unsigned char *buf, int buflen);
+EXTERNC void OSS_drum_caching (int dev, int chn, int patch, int fd,
+ unsigned char *buf, int buflen);
+EXTERNC void OSS_write_patch (int fd, unsigned char *buf, int len);
+EXTERNC int OSS_write_patch2 (int fd, unsigned char *buf, int len);
+
+#define SEQ_PM_DEFINES int __foo_bar___
+#ifdef OSSLIB
+# define SEQ_USE_EXTBUF() \
+ EXTERNC unsigned char *_seqbuf; \
+ EXTERNC int _seqbuflen;EXTERNC int _seqbufptr
+# define SEQ_DEFINEBUF(len) SEQ_USE_EXTBUF();static int _requested_seqbuflen=len
+# define _SEQ_ADVBUF(len) OSS_seq_advbuf(len, seqfd, _seqbuf, _seqbuflen)
+# define _SEQ_NEEDBUF(len) OSS_seq_needbuf(len, seqfd, _seqbuf, _seqbuflen)
+# define SEQ_DUMPBUF() OSS_seqbuf_dump(seqfd, _seqbuf, _seqbuflen)
+
+# define SEQ_LOAD_GMINSTR(dev, instr) \
+ OSS_patch_caching(dev, -1, instr, seqfd, _seqbuf, _seqbuflen)
+# define SEQ_LOAD_GMDRUM(dev, drum) \
+ OSS_drum_caching(dev, -1, drum, seqfd, _seqbuf, _seqbuflen)
+#else /* !OSSLIB */
+
+# define SEQ_LOAD_GMINSTR(dev, instr)
+# define SEQ_LOAD_GMDRUM(dev, drum)
+
+# define SEQ_USE_EXTBUF() \
+ EXTERNC unsigned char _seqbuf[]; \
+ EXTERNC int _seqbuflen;EXTERNC int _seqbufptr
+
+#ifndef USE_SIMPLE_MACROS
+/* Sample seqbuf_dump() implementation:
+ *
+ * SEQ_DEFINEBUF (2048); -- Defines a buffer for 2048 bytes
+ *
+ * int seqfd; -- The file descriptor for /dev/sequencer.
+ *
+ * void
+ * seqbuf_dump ()
+ * {
+ * if (_seqbufptr)
+ * if (write (seqfd, _seqbuf, _seqbufptr) == -1)
+ * {
+ * perror ("write /dev/sequencer");
+ * exit (-1);
+ * }
+ * _seqbufptr = 0;
+ * }
+ */
+
+#define SEQ_DEFINEBUF(len) \
+ unsigned char _seqbuf[len]; int _seqbuflen = len;int _seqbufptr = 0
+#define _SEQ_NEEDBUF(len) \
+ if ((_seqbufptr+(len)) > _seqbuflen) seqbuf_dump()
+#define _SEQ_ADVBUF(len) _seqbufptr += len
+#define SEQ_DUMPBUF seqbuf_dump
+#else
+/*
+ * This variation of the sequencer macros is used just to format one event
+ * using fixed buffer.
+ *
+ * The program using the macro library must define the following macros before
+ * using this library.
+ *
+ * #define _seqbuf name of the buffer (unsigned char[])
+ * #define _SEQ_ADVBUF(len) If the applic needs to know the exact
+ * size of the event, this macro can be used.
+ * Otherwise this must be defined as empty.
+ * #define _seqbufptr Define the name of index variable or 0 if
+ * not required.
+ */
+#define _SEQ_NEEDBUF(len) /* empty */
+#endif
+#endif /* !OSSLIB */
+
+#define SEQ_VOLUME_MODE(dev, mode) \
+ {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = SEQ_EXTENDED;\
+ _seqbuf[_seqbufptr+1] = SEQ_VOLMODE;\
+ _seqbuf[_seqbufptr+2] = (dev);\
+ _seqbuf[_seqbufptr+3] = (mode);\
+ _seqbuf[_seqbufptr+4] = 0;\
+ _seqbuf[_seqbufptr+5] = 0;\
+ _seqbuf[_seqbufptr+6] = 0;\
+ _seqbuf[_seqbufptr+7] = 0;\
+ _SEQ_ADVBUF(8);}
+
+/*
+ * Midi voice messages
+ */
+
+#define _CHN_VOICE(dev, event, chn, note, parm) \
+ {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = EV_CHN_VOICE;\
+ _seqbuf[_seqbufptr+1] = (dev);\
+ _seqbuf[_seqbufptr+2] = (event);\
+ _seqbuf[_seqbufptr+3] = (chn);\
+ _seqbuf[_seqbufptr+4] = (note);\
+ _seqbuf[_seqbufptr+5] = (parm);\
+ _seqbuf[_seqbufptr+6] = (0);\
+ _seqbuf[_seqbufptr+7] = 0;\
+ _SEQ_ADVBUF(8);}
+
+#define SEQ_START_NOTE(dev, chn, note, vol) \
+ _CHN_VOICE(dev, MIDI_NOTEON, chn, note, vol)
+
+#define SEQ_STOP_NOTE(dev, chn, note, vol) \
+ _CHN_VOICE(dev, MIDI_NOTEOFF, chn, note, vol)
+
+#define SEQ_KEY_PRESSURE(dev, chn, note, pressure) \
+ _CHN_VOICE(dev, MIDI_KEY_PRESSURE, chn, note, pressure)
+
+/*
+ * Midi channel messages
+ */
+
+#define _CHN_COMMON(dev, event, chn, p1, p2, w14) \
+ {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = EV_CHN_COMMON;\
+ _seqbuf[_seqbufptr+1] = (dev);\
+ _seqbuf[_seqbufptr+2] = (event);\
+ _seqbuf[_seqbufptr+3] = (chn);\
+ _seqbuf[_seqbufptr+4] = (p1);\
+ _seqbuf[_seqbufptr+5] = (p2);\
+ *(short *)&_seqbuf[_seqbufptr+6] = (w14);\
+ _SEQ_ADVBUF(8);}
+/*
+ * SEQ_SYSEX permits sending of sysex messages. (It may look that it permits
+ * sending any MIDI bytes but it's absolutely not possible. Trying to do
+ * so _will_ cause problems with MPU401 intelligent mode).
+ *
+ * Sysex messages are sent in blocks of 1 to 6 bytes. Longer messages must be
+ * sent by calling SEQ_SYSEX() several times (there must be no other events
+ * between them). First sysex fragment must have 0xf0 in the first byte
+ * and the last byte (buf[len-1] of the last fragment must be 0xf7. No byte
+ * between these sysex start and end markers cannot be larger than 0x7f. Also
+ * lengths of each fragments (except the last one) must be 6.
+ *
+ * Breaking the above rules may work with some MIDI ports but is likely to
+ * cause fatal problems with some other devices (such as MPU401).
+ */
+#define SEQ_SYSEX(dev, buf, len) \
+ {int ii, ll=(len); \
+ unsigned char *bufp=buf;\
+ if (ll>6)ll=6;\
+ _SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = EV_SYSEX;\
+ _seqbuf[_seqbufptr+1] = (dev);\
+ for(ii=0;ii<ll;ii++)\
+ _seqbuf[_seqbufptr+ii+2] = bufp[ii];\
+ for(ii=ll;ii<6;ii++)\
+ _seqbuf[_seqbufptr+ii+2] = 0xff;\
+ _SEQ_ADVBUF(8);}
+
+#define SEQ_CHN_PRESSURE(dev, chn, pressure) \
+ _CHN_COMMON(dev, MIDI_CHN_PRESSURE, chn, pressure, 0, 0)
+
+#define SEQ_SET_PATCH SEQ_PGM_CHANGE
+#ifdef OSSLIB
+# define SEQ_PGM_CHANGE(dev, chn, patch) \
+ {OSS_patch_caching(dev, chn, patch, seqfd, _seqbuf, _seqbuflen); \
+ _CHN_COMMON(dev, MIDI_PGM_CHANGE, chn, patch, 0, 0);}
+#else
+# define SEQ_PGM_CHANGE(dev, chn, patch) \
+ _CHN_COMMON(dev, MIDI_PGM_CHANGE, chn, patch, 0, 0)
+#endif
+
+#define SEQ_CONTROL(dev, chn, controller, value) \
+ _CHN_COMMON(dev, MIDI_CTL_CHANGE, chn, controller, 0, value)
+
+#define SEQ_BENDER(dev, chn, value) \
+ _CHN_COMMON(dev, MIDI_PITCH_BEND, chn, 0, 0, value)
+
+#define SEQ_V2_X_CONTROL(dev, voice, controller, value) \
+ {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = SEQ_EXTENDED;\
+ _seqbuf[_seqbufptr+1] = SEQ_CONTROLLER;\
+ _seqbuf[_seqbufptr+2] = (dev);\
+ _seqbuf[_seqbufptr+3] = (voice);\
+ _seqbuf[_seqbufptr+4] = (controller);\
+ _seqbuf[_seqbufptr+5] = ((value)&0xff);\
+ _seqbuf[_seqbufptr+6] = ((value>>8)&0xff);\
+ _seqbuf[_seqbufptr+7] = 0;\
+ _SEQ_ADVBUF(8);}
+/*
+ * The following 5 macros are incorrectly implemented and obsolete.
+ * Use SEQ_BENDER and SEQ_CONTROL (with proper controller) instead.
+ */
+#define SEQ_PITCHBEND(dev, voice, value) \
+ SEQ_V2_X_CONTROL(dev, voice, CTRL_PITCH_BENDER, value)
+#define SEQ_BENDER_RANGE(dev, voice, value) \
+ SEQ_V2_X_CONTROL(dev, voice, CTRL_PITCH_BENDER_RANGE, value)
+#define SEQ_EXPRESSION(dev, voice, value) \
+ SEQ_CONTROL(dev, voice, CTL_EXPRESSION, value*128)
+#define SEQ_MAIN_VOLUME(dev, voice, value) \
+ SEQ_CONTROL(dev, voice, CTL_MAIN_VOLUME, (value*16383)/100)
+#define SEQ_PANNING(dev, voice, pos) \
+ SEQ_CONTROL(dev, voice, CTL_PAN, (pos+128) / 2)
+
+/*
+ * Timing and syncronization macros
+ */
+
+#define _TIMER_EVENT(ev, parm) {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr+0] = EV_TIMING; \
+ _seqbuf[_seqbufptr+1] = (ev); \
+ _seqbuf[_seqbufptr+2] = 0;\
+ _seqbuf[_seqbufptr+3] = 0;\
+ *(unsigned int *)&_seqbuf[_seqbufptr+4] = (parm); \
+ _SEQ_ADVBUF(8);}
+
+#define SEQ_START_TIMER() _TIMER_EVENT(TMR_START, 0)
+#define SEQ_STOP_TIMER() _TIMER_EVENT(TMR_STOP, 0)
+#define SEQ_CONTINUE_TIMER() _TIMER_EVENT(TMR_CONTINUE, 0)
+#define SEQ_WAIT_TIME(ticks) _TIMER_EVENT(TMR_WAIT_ABS, ticks)
+#define SEQ_DELTA_TIME(ticks) _TIMER_EVENT(TMR_WAIT_REL, ticks)
+#define SEQ_ECHO_BACK(key) _TIMER_EVENT(TMR_ECHO, key)
+#define SEQ_SET_TEMPO(value) _TIMER_EVENT(TMR_TEMPO, value)
+#define SEQ_SONGPOS(pos) _TIMER_EVENT(TMR_SPP, pos)
+#define SEQ_TIME_SIGNATURE(sig) _TIMER_EVENT(TMR_TIMESIG, sig)
+
+/*
+ * Local control events
+ */
+
+#define _LOCAL_EVENT(ev, parm) {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr+0] = EV_SEQ_LOCAL; \
+ _seqbuf[_seqbufptr+1] = (ev); \
+ _seqbuf[_seqbufptr+2] = 0;\
+ _seqbuf[_seqbufptr+3] = 0;\
+ *(unsigned int *)&_seqbuf[_seqbufptr+4] = (parm); \
+ _SEQ_ADVBUF(8);}
+
+#define SEQ_PLAYAUDIO(devmask) _LOCAL_EVENT(LOCL_STARTAUDIO, devmask)
+#define SEQ_PLAYAUDIO2(devmask) _LOCAL_EVENT(LOCL_STARTAUDIO2, devmask)
+#define SEQ_PLAYAUDIO3(devmask) _LOCAL_EVENT(LOCL_STARTAUDIO3, devmask)
+#define SEQ_PLAYAUDIO4(devmask) _LOCAL_EVENT(LOCL_STARTAUDIO4, devmask)
+/*
+ * Events for the level 1 interface only
+ */
+
+#define SEQ_MIDIOUT(device, byte) {_SEQ_NEEDBUF(4);\
+ _seqbuf[_seqbufptr] = SEQ_MIDIPUTC;\
+ _seqbuf[_seqbufptr+1] = (byte);\
+ _seqbuf[_seqbufptr+2] = (device);\
+ _seqbuf[_seqbufptr+3] = 0;\
+ _SEQ_ADVBUF(4);}
+
+/*
+ * Patch loading.
+ */
+#ifdef OSSLIB
+# define SEQ_WRPATCH(patchx, len) \
+ OSS_write_patch(seqfd, (char*)(patchx), len)
+# define SEQ_WRPATCH2(patchx, len) \
+ OSS_write_patch2(seqfd, (char*)(patchx), len)
+#else
+# define SEQ_WRPATCH(patchx, len) \
+ {if (_seqbufptr) SEQ_DUMPBUF();\
+ if (write(seqfd, (char*)(patchx), len)==-1) \
+ perror("Write patch: /dev/sequencer");}
+# define SEQ_WRPATCH2(patchx, len) \
+ (SEQ_DUMPBUF(), write(seqfd, (char*)(patchx), len))
+#endif
+
+#endif
+#endif /* ifndef DISABLE_SEQUENCER */
+
+/*
+ ****************************************************************************
+ * ioctl commands for the /dev/midi##
+ ****************************************************************************/
+#define SNDCTL_MIDI_PRETIME __SIOWR('m', 0, int)
+
+#if 0
+/*
+ * The SNDCTL_MIDI_MPUMODE and SNDCTL_MIDI_MPUCMD calls
+ * are completely obsolete. The hardware device (MPU-401 "intelligent mode"
+ * and compatibles) has disappeared from the market 10 years ago so there
+ * is no need for this stuff. The MPU-401 "UART" mode devices don't support
+ * this stuff.
+ */
+typedef struct
+{
+ unsigned char cmd;
+ char nr_args, nr_returns;
+ unsigned char data[30];
+} mpu_command_rec;
+
+#define SNDCTL_MIDI_MPUMODE __SIOWR('m', 1, int)
+#define SNDCTL_MIDI_MPUCMD __SIOWR('m', 2, mpu_command_rec)
+#endif
+
+/*
+ * SNDCTL_MIDI_MTCINPUT turns on a mode where OSS automatically inserts
+ * MTC quarter frame messages (F1 xx) to the input.
+ * The argument is the MTC mode:
+ *
+ * -1 = Turn MTC messages OFF (default)
+ * 24 = 24 FPS
+ * 25 = 25 FPS
+ * 29 = 30 FPS drop frame
+ * 30 = 30 FPS
+ *
+ * Note that 25 FPS mode is probably the only mode that is supported. Other
+ * modes may be supported in the future versions of OSS, 25 FPS is handy
+ * because it generates 25*4=100 quarter frame messages per second which
+ * matches the usual 100 HZ system timer rate).
+ *
+ * The quarter frame timer will be reset to 0:00:00:00.0 at the moment this
+ * ioctl is made.
+ */
+#define SNDCTL_MIDI_MTCINPUT __SIOWR('m', 3, int)
+
+/*
+ * MTC/SMPTE time code record (for future use)
+ */
+typedef struct
+{
+ unsigned char hours, minutes, seconds, frames, qframes;
+ char direction;
+#define MTC_DIR_STOPPED 0
+#define MTC_DIR_FORWARD 1
+#define MTC_DIR_BACKWARD -1
+ unsigned char time_code_type;
+ unsigned int flags;
+} oss_mtc_data_t;
+
+#define SNDCTL_MIDI_SETMODE __SIOWR('m', 6, int)
+# define MIDI_MODE_TRADITIONAL 0
+# define MIDI_MODE_TIMED 1 /* Input times are in MIDI ticks */
+# define MIDI_MODE_TIMED_ABS 2 /* Input times are absolute (usecs) */
+
+/*
+ * Packet header for MIDI_MODE_TIMED and MIDI_MODE_TIMED_ABS
+ */
+typedef unsigned long long oss_midi_time_t; /* Variable type for MIDI time (clock ticks) */
+
+typedef struct
+{
+ int magic; /* Initialize to MIDI_HDR_MAGIC */
+#define MIDI_HDR_MAGIC -1
+ unsigned short event_type;
+#define MIDI_EV_WRITE 0 /* Write or read (with payload) */
+#define MIDI_EV_TEMPO 1
+#define MIDI_EV_ECHO 2
+#define MIDI_EV_START 3
+#define MIDI_EV_STOP 4
+#define MIDI_EV_CONTINUE 5
+#define MIDI_EV_XPRESSWRITE 6
+#define MIDI_EV_TIMEBASE 7
+#define MIDI_EV_DEVCTL 8 /* Device control read/write */
+ unsigned short options;
+#define MIDI_OPT_NONE 0x0000
+#define MIDI_OPT_TIMED 0x0001
+#define MIDI_OPT_CONTINUATION 0x0002
+#define MIDI_OPT_USECTIME 0x0004 /* Time is absolute (in usecs) */
+#define MIDI_OPT_BUSY 0x0008 /* Reserved for internal use */
+ oss_midi_time_t time;
+ int parm;
+ int filler[3]; /* Fur future expansion - init to zeros */
+} midi_packet_header_t;
+/*
+ * MIDI_PAYLOAD_SIZE is the maximum size of one MIDI input chunk. It must be
+ * less (or equal) than 1024 which is the read size recommended in the
+ * documentation. TODO: Explain this better.
+ */
+#define MIDI_PAYLOAD_SIZE 1000
+
+typedef struct
+{
+ midi_packet_header_t hdr;
+ unsigned char payload[MIDI_PAYLOAD_SIZE];
+} midi_packet_t;
+
+#define SNDCTL_MIDI_TIMEBASE __SIOWR('m', 7, int)
+#define SNDCTL_MIDI_TEMPO __SIOWR('m', 8, int)
+/*
+ * User land MIDI servers (synths) can use SNDCTL_MIDI_SET_LATENCY
+ * to request MIDI events to be sent to them in advance. The parameter
+ * (in microseconds) tells how much before the events are submitted.
+ *
+ * This feature is only valid for loopback devices and possibly some other
+ * types of virtual devices.
+ */
+#define SNDCTL_MIDI_SET_LATENCY __SIOW ('m', 9, int)
+/*
+ ****************************************************************************
+ * IOCTL commands for /dev/dsp
+ ****************************************************************************/
+
+#define SNDCTL_DSP_HALT __SIO ('P', 0)
+#define SNDCTL_DSP_RESET SNDCTL_DSP_HALT /* Old name */
+#define SNDCTL_DSP_SYNC __SIO ('P', 1)
+#define SNDCTL_DSP_SPEED __SIOWR('P', 2, int)
+
+/* SNDCTL_DSP_STEREO is obsolete - use SNDCTL_DSP_CHANNELS instead */
+#define SNDCTL_DSP_STEREO __SIOWR('P', 3, int)
+/* SNDCTL_DSP_STEREO is obsolete - use SNDCTL_DSP_CHANNELS instead */
+
+#define SNDCTL_DSP_GETBLKSIZE __SIOWR('P', 4, int)
+#define SNDCTL_DSP_SAMPLESIZE SNDCTL_DSP_SETFMT
+#define SNDCTL_DSP_CHANNELS __SIOWR('P', 6, int)
+#define SNDCTL_DSP_POST __SIO ('P', 8)
+#define SNDCTL_DSP_SUBDIVIDE __SIOWR('P', 9, int)
+#define SNDCTL_DSP_SETFRAGMENT __SIOWR('P',10, int)
+
+/* Audio data formats (Note! U8=8 and S16_LE=16 for compatibility) */
+#define SNDCTL_DSP_GETFMTS __SIOR ('P',11, int) /* Returns a mask */
+#define SNDCTL_DSP_SETFMT __SIOWR('P',5, int) /* Selects ONE fmt */
+# define AFMT_QUERY 0x00000000 /* Return current fmt */
+# define AFMT_MU_LAW 0x00000001
+# define AFMT_A_LAW 0x00000002
+# define AFMT_IMA_ADPCM 0x00000004
+# define AFMT_U8 0x00000008
+# define AFMT_S16_LE 0x00000010 /* Little endian signed 16 */
+# define AFMT_S16_BE 0x00000020 /* Big endian signed 16 */
+# define AFMT_S8 0x00000040
+# define AFMT_U16_LE 0x00000080 /* Little endian U16 */
+# define AFMT_U16_BE 0x00000100 /* Big endian U16 */
+# define AFMT_MPEG 0x00000200 /* MPEG (2) audio */
+
+/* AC3 _compressed_ bitstreams (See Programmer's Guide for details). */
+# define AFMT_AC3 0x00000400
+/* Ogg Vorbis _compressed_ bit streams */
+# define AFMT_VORBIS 0x00000800
+
+/* 32 bit formats (MSB aligned) formats */
+# define AFMT_S32_LE 0x00001000
+# define AFMT_S32_BE 0x00002000
+
+/* Reserved for _native_ endian double precision IEEE floating point */
+# define AFMT_FLOAT 0x00004000
+
+/* 24 bit formats (LSB aligned in 32 bit word) formats */
+# define AFMT_S24_LE 0x00008000
+# define AFMT_S24_BE 0x00010000
+
+/*
+ * S/PDIF raw format. In this format the S/PDIF frames (including all
+ * control and user bits) are included in the data stream. Each sample
+ * is stored in a 32 bit frame (see IEC-958 for more info). This format
+ * is supported by very few devices and it's only usable for purposes
+ * where full access to the control/user bits is required (real time control).
+ */
+# define AFMT_SPDIF_RAW 0x00020000
+
+/* 24 bit packed (3 byte) little endian format (USB compatibility) */
+# define AFMT_S24_PACKED 0x00040000
+
+
+/*
+ * Some big endian/little endian handling macros (native endian and opposite
+ * endian formats). The usage of these macros is described in the OSS
+ * Programmer's Manual.
+ */
+
+#if defined(_AIX) || defined(AIX) || defined(sparc) || defined(__hppa) || defined(PPC) || defined(__powerpc__) && !defined(i386) && !defined(__i386) && !defined(__i386__)
+
+/* Big endian machines */
+# define _PATCHKEY(id) (0xfd00|id)
+# define AFMT_S16_NE AFMT_S16_BE
+# define AFMT_U16_NE AFMT_U16_BE
+# define AFMT_S32_NE AFMT_S32_BE
+# define AFMT_S24_NE AFMT_S24_BE
+# define AFMT_S16_OE AFMT_S16_LE
+# define AFMT_S32_OE AFMT_S32_LE
+# define AFMT_S24_OE AFMT_S24_LE
+#else
+# define _PATCHKEY(id) ((id<<8)|0xfd)
+# define AFMT_S16_NE AFMT_S16_LE
+# define AFMT_U16_NE AFMT_U16_LE
+# define AFMT_S32_NE AFMT_S32_LE
+# define AFMT_S24_NE AFMT_S24_LE
+# define AFMT_S16_OE AFMT_S16_BE
+# define AFMT_S32_OE AFMT_S32_BE
+# define AFMT_S24_OE AFMT_S24_BE
+#endif
+/*
+ * Buffer status queries.
+ */
+typedef struct audio_buf_info
+{
+ int fragments; /* # of available fragments (partially usend ones not counted) */
+ int fragstotal; /* Total # of fragments allocated */
+ int fragsize; /* Size of a fragment in bytes */
+ int bytes; /* Available space in bytes (includes partially used fragments) */
+ /* Note! 'bytes' could be more than fragments*fragsize */
+} audio_buf_info;
+
+#define SNDCTL_DSP_GETOSPACE __SIOR ('P',12, audio_buf_info)
+#define SNDCTL_DSP_GETISPACE __SIOR ('P',13, audio_buf_info)
+#define SNDCTL_DSP_GETCAPS __SIOR ('P',15, int)
+# define PCM_CAP_REVISION 0x000000ff /* Bits for revision level (0 to 255) */
+# define PCM_CAP_DUPLEX 0x00000100 /* Full duplex record/playback */
+# define PCM_CAP_REALTIME 0x00000200 /* Not in use */
+# define PCM_CAP_BATCH 0x00000400 /* Device has some kind of */
+ /* internal buffers which may */
+ /* cause some delays and */
+ /* decrease precision of timing */
+# define PCM_CAP_COPROC 0x00000800 /* Has a coprocessor */
+ /* Sometimes it's a DSP */
+ /* but usually not */
+# define PCM_CAP_TRIGGER 0x00001000 /* Supports SETTRIGGER */
+# define PCM_CAP_MMAP 0x00002000 /* Supports mmap() */
+# define PCM_CAP_MULTI 0x00004000 /* Supports multiple open */
+# define PCM_CAP_BIND 0x00008000 /* Supports binding to front/rear/center/lfe */
+# define PCM_CAP_INPUT 0x00010000 /* Supports recording */
+# define PCM_CAP_OUTPUT 0x00020000 /* Supports playback */
+# define PCM_CAP_VIRTUAL 0x00040000 /* Virtual device */
+/* 0x00040000 and 0x00080000 reserved for future use */
+
+/* Analog/digital control capabilities */
+# define PCM_CAP_ANALOGOUT 0x00100000
+# define PCM_CAP_ANALOGIN 0x00200000
+# define PCM_CAP_DIGITALOUT 0x00400000
+# define PCM_CAP_DIGITALIN 0x00800000
+# define PCM_CAP_ADMASK 0x00f00000
+/*
+ * NOTE! (capabilities & PCM_CAP_ADMASK)==0 means just that the
+ * digital/analog interface control features are not supported by the
+ * device/driver. However the device still supports analog, digital or
+ * both inputs/outputs (depending on the device). See the OSS Programmer's
+ * Guide for full details.
+ */
+# define PCM_CAP_SHADOW 0x01000000 /* "Shadow" device */
+
+/*
+ * Preferred channel usage. These bits can be used to
+ * give recommendations to the application. Used by few drivers.
+ * For example if ((caps & DSP_CH_MASK) == DSP_CH_MONO) means that
+ * the device works best in mono mode. However it doesn't necessarily mean
+ * that the device cannot be used in stereo. These bits should only be used
+ * by special applications such as multi track hard disk recorders to find
+ * out the initial setup. However the user should be able to override this
+ * selection.
+ *
+ * To find out which modes are actually supported the application should
+ * try to select them using SNDCTL_DSP_CHANNELS.
+ */
+# define DSP_CH_MASK 0x06000000 /* Mask */
+# define DSP_CH_ANY 0x00000000 /* No preferred mode */
+# define DSP_CH_MONO 0x02000000
+# define DSP_CH_STEREO 0x04000000
+# define DSP_CH_MULTI 0x06000000 /* More than two channels */
+
+# define PCM_CAP_HIDDEN 0x08000000 /* Hidden device */
+# define PCM_CAP_FREERATE 0x10000000
+# define PCM_CAP_MODEM 0x20000000 /* Modem device */
+# define PCM_CAP_DEFAULT 0x40000000 /* "Default" device */
+
+/*
+ * The PCM_CAP_* capability names were known as DSP_CAP_* prior OSS 4.0
+ * so it's necessary to define the older names too.
+ */
+#define DSP_CAP_ADMASK PCM_CAP_ADMASK
+#define DSP_CAP_ANALOGIN PCM_CAP_ANALOGIN
+#define DSP_CAP_ANALOGOUT PCM_CAP_ANALOGOUT
+#define DSP_CAP_BATCH PCM_CAP_BATCH
+#define DSP_CAP_BIND PCM_CAP_BIND
+#define DSP_CAP_COPROC PCM_CAP_COPROC
+#define DSP_CAP_DEFAULT PCM_CAP_DEFAULT
+#define DSP_CAP_DIGITALIN PCM_CAP_DIGITALIN
+#define DSP_CAP_DIGITALOUT PCM_CAP_DIGITALOUT
+#define DSP_CAP_DUPLEX PCM_CAP_DUPLEX
+#define DSP_CAP_FREERATE PCM_CAP_FREERATE
+#define DSP_CAP_HIDDEN PCM_CAP_HIDDEN
+#define DSP_CAP_INPUT PCM_CAP_INPUT
+#define DSP_CAP_MMAP PCM_CAP_MMAP
+#define DSP_CAP_MODEM PCM_CAP_MODEM
+#define DSP_CAP_MULTI PCM_CAP_MULTI
+#define DSP_CAP_OUTPUT PCM_CAP_OUTPUT
+#define DSP_CAP_REALTIME PCM_CAP_REALTIME
+#define DSP_CAP_REVISION PCM_CAP_REVISION
+#define DSP_CAP_SHADOW PCM_CAP_SHADOW
+#define DSP_CAP_TRIGGER PCM_CAP_TRIGGER
+#define DSP_CAP_VIRTUAL PCM_CAP_VIRTUAL
+
+#define SNDCTL_DSP_GETTRIGGER __SIOR ('P',16, int)
+#define SNDCTL_DSP_SETTRIGGER __SIOW ('P',16, int)
+# define PCM_ENABLE_INPUT 0x00000001
+# define PCM_ENABLE_OUTPUT 0x00000002
+
+typedef struct count_info
+{
+ unsigned int bytes; /* Total # of bytes processed */
+ int blocks; /* # of fragment transitions since last time */
+ int ptr; /* Current DMA pointer value */
+} count_info;
+
+#define SNDCTL_DSP_GETIPTR __SIOR ('P',17, count_info)
+#define SNDCTL_DSP_GETOPTR __SIOR ('P',18, count_info)
+
+typedef struct buffmem_desc
+{
+ unsigned *buffer;
+ int size;
+} buffmem_desc;
+#define SNDCTL_DSP_SETSYNCRO __SIO ('P', 21)
+#define SNDCTL_DSP_SETDUPLEX __SIO ('P', 22)
+
+#define SNDCTL_DSP_PROFILE __SIOW ('P', 23, int) /* OBSOLETE */
+#define APF_NORMAL 0 /* Normal applications */
+#define APF_NETWORK 1 /* Underruns probably caused by an "external" delay */
+#define APF_CPUINTENS 2 /* Underruns probably caused by "overheating" the CPU */
+
+#define SNDCTL_DSP_GETODELAY __SIOR ('P', 23, int)
+
+typedef struct audio_errinfo
+{
+ int play_underruns;
+ int rec_overruns;
+ unsigned int play_ptradjust;
+ unsigned int rec_ptradjust;
+ int play_errorcount;
+ int rec_errorcount;
+ int play_lasterror;
+ int rec_lasterror;
+ int play_errorparm;
+ int rec_errorparm;
+ int filler[16];
+} audio_errinfo;
+
+#define SNDCTL_DSP_GETPLAYVOL __SIOR ('P', 24, int)
+#define SNDCTL_DSP_SETPLAYVOL __SIOWR('P', 24, int)
+#define SNDCTL_DSP_GETERROR __SIOR ('P', 25, audio_errinfo)
+/*
+ ****************************************************************************
+ * Digital interface (S/PDIF) control interface
+ */
+
+typedef struct oss_digital_control
+{
+ unsigned int caps;
+#define DIG_CBITIN_NONE 0x00000000
+#define DIG_CBITIN_LIMITED 0x00000001
+#define DIG_CBITIN_DATA 0x00000002
+#define DIG_CBITIN_BYTE0 0x00000004
+#define DIG_CBITIN_FULL 0x00000008
+#define DIG_CBITIN_MASK 0x0000000f
+#define DIG_CBITOUT_NONE 0x00000000
+#define DIG_CBITOUT_LIMITED 0x00000010
+#define DIG_CBITOUT_BYTE0 0x00000020
+#define DIG_CBITOUT_FULL 0x00000040
+#define DIG_CBITOUT_DATA 0x00000080
+#define DIG_CBITOUT_MASK 0x000000f0
+#define DIG_UBITIN 0x00000100
+#define DIG_UBITOUT 0x00000200
+#define DIG_VBITOUT 0x00000400
+#define DIG_OUTRATE 0x00000800
+#define DIG_INRATE 0x00001000
+#define DIG_INBITS 0x00002000
+#define DIG_OUTBITS 0x00004000
+#define DIG_EXACT 0x00010000
+#define DIG_PRO 0x00020000
+#define DIG_CONSUMER 0x00040000
+#define DIG_PASSTHROUGH 0x00080000
+#define DIG_OUTSEL 0x00100000
+
+ unsigned int valid;
+#define VAL_CBITIN 0x00000001
+#define VAL_UBITIN 0x00000002
+#define VAL_CBITOUT 0x00000004
+#define VAL_UBITOUT 0x00000008
+#define VAL_ISTATUS 0x00000010
+#define VAL_IRATE 0x00000020
+#define VAL_ORATE 0x00000040
+#define VAL_INBITS 0x00000080
+#define VAL_OUTBITS 0x00000100
+#define VAL_REQUEST 0x00000200
+#define VAL_OUTSEL 0x00000400
+
+#define VAL_OUTMASK (VAL_CBITOUT|VAL_UBITOUT|VAL_ORATE|VAL_OUTBITS|VAL_OUTSEL)
+
+ unsigned int request, param;
+#define SPD_RQ_PASSTHROUGH 1
+
+ unsigned char cbitin[24];
+ unsigned char ubitin[24];
+ unsigned char cbitout[24];
+ unsigned char ubitout[24];
+
+ unsigned int outsel;
+#define OUTSEL_DIGITAL 1
+#define OUTSEL_ANALOG 2
+#define OUTSEL_BOTH (OUTSEL_DIGITAL|OUTSEL_ANALOG)
+
+ int in_data; /* Audio/data if autodetectable by the receiver */
+#define IND_UNKNOWN 0
+#define IND_AUDIO 1
+#define IND_DATA 2
+
+ int in_locked; /* Receiver locked */
+#define LOCK_NOT_INDICATED 0
+#define LOCK_UNLOCKED 1
+#define LOCK_LOCKED 2
+
+ int in_quality; /* Input signal quality */
+#define IN_QUAL_NOT_INDICATED 0
+#define IN_QUAL_POOR 1
+#define IN_QUAL_GOOD 2
+
+ int in_vbit, out_vbit; /* V bits */
+#define VBIT_NOT_INDICATED 0
+#define VBIT_OFF 1
+#define VBIT_ON 2
+
+ unsigned int in_errors; /* Various input error conditions */
+#define INERR_CRC 0x0001
+#define INERR_QCODE_CRC 0x0002
+#define INERR_PARITY 0x0004
+#define INERR_BIPHASE 0x0008
+
+ int srate_in, srate_out;
+ int bits_in, bits_out;
+
+ int filler[32];
+} oss_digital_control;
+
+#define SNDCTL_DSP_READCTL __SIOWR('P', 26, oss_digital_control)
+#define SNDCTL_DSP_WRITECTL __SIOWR('P', 27, oss_digital_control)
+
+/*
+ ****************************************************************************
+ * Sync groups for audio devices
+ */
+typedef struct oss_syncgroup
+{
+ int id;
+ int mode;
+ int filler[16];
+} oss_syncgroup;
+
+#define SNDCTL_DSP_SYNCGROUP __SIOWR('P', 28, oss_syncgroup)
+#define SNDCTL_DSP_SYNCSTART __SIOW ('P', 29, int)
+
+/*
+ **************************************************************************
+ * "cooked" mode enables software based conversions for sample rate, sample
+ * format (bits) and number of channels (mono/stereo). These conversions are
+ * required with some devices that support only one sample rate or just stereo
+ * to let the applications to use other formats. The cooked mode is enabled by
+ * default. However it's necessary to disable this mode when mmap() is used or
+ * when very deterministic timing is required. SNDCTL_DSP_COOKEDMODE is an
+ * optional call introduced in OSS 3.9.6f. It's _error return must be ignored_
+ * since normally this call will return erno=EINVAL.
+ *
+ * SNDCTL_DSP_COOKEDMODE must be called immediately after open before doing
+ * anything else. Otherwise the call will not have any effect.
+ */
+#define SNDCTL_DSP_COOKEDMODE __SIOW ('P', 30, int)
+
+/*
+ **************************************************************************
+ * SNDCTL_DSP_SILENCE and SNDCTL_DSP_SKIP are new calls in OSS 3.99.0
+ * that can be used to implement pause/continue during playback (no effect
+ * on recording).
+ */
+#define SNDCTL_DSP_SILENCE __SIO ('P', 31)
+#define SNDCTL_DSP_SKIP __SIO ('P', 32)
+/*
+ ****************************************************************************
+ * Abort transfer (reset) functions for input and output
+ */
+#define SNDCTL_DSP_HALT_INPUT __SIO ('P', 33)
+#define SNDCTL_DSP_RESET_INPUT SNDCTL_DSP_HALT_INPUT /* Old name */
+#define SNDCTL_DSP_HALT_OUTPUT __SIO ('P', 34)
+#define SNDCTL_DSP_RESET_OUTPUT SNDCTL_DSP_HALT_OUTPUT /* Old name */
+/*
+ ****************************************************************************
+ * Low water level control
+ */
+#define SNDCTL_DSP_LOW_WATER __SIOW ('P', 34, int)
+
+/*
+ ****************************************************************************
+ * 64 bit pointer support. Only available in environments that support
+ * the 64 bit (long long) integer type.
+ */
+#ifndef OSS_NO_LONG_LONG
+typedef struct
+{
+ long long samples;
+ int fifo_samples;
+ int filler[32]; /* For future use */
+} oss_count_t;
+
+#define SNDCTL_DSP_CURRENT_IPTR __SIOR ('P', 35, oss_count_t)
+#define SNDCTL_DSP_CURRENT_OPTR __SIOR ('P', 36, oss_count_t)
+#endif
+
+/*
+ ****************************************************************************
+ * Interface for selecting recording sources and playback output routings.
+ */
+#define SNDCTL_DSP_GET_RECSRC_NAMES __SIOR ('P', 37, oss_mixer_enuminfo)
+#define SNDCTL_DSP_GET_RECSRC __SIOR ('P', 38, int)
+#define SNDCTL_DSP_SET_RECSRC __SIOWR('P', 38, int)
+
+#define SNDCTL_DSP_GET_PLAYTGT_NAMES __SIOR ('P', 39, oss_mixer_enuminfo)
+#define SNDCTL_DSP_GET_PLAYTGT __SIOR ('P', 40, int)
+#define SNDCTL_DSP_SET_PLAYTGT __SIOWR('P', 40, int)
+#define SNDCTL_DSP_GETRECVOL __SIOR ('P', 41, int)
+#define SNDCTL_DSP_SETRECVOL __SIOWR('P', 41, int)
+
+/*
+ ***************************************************************************
+ * Some calls for setting the channel assignment with multi channel devices
+ * (see the manual for details).
+ */
+#ifndef OSS_NO_LONG_LONG
+#define SNDCTL_DSP_GET_CHNORDER __SIOR ('P', 42, unsigned long long)
+#define SNDCTL_DSP_SET_CHNORDER __SIOWR('P', 42, unsigned long long)
+# define CHID_UNDEF 0
+# define CHID_L 1
+# define CHID_R 2
+# define CHID_C 3
+# define CHID_LFE 4
+# define CHID_LS 5
+# define CHID_RS 6
+# define CHID_LR 7
+# define CHID_RR 8
+#define CHNORDER_UNDEF 0x0000000000000000ULL
+#define CHNORDER_NORMAL 0x0000000087654321ULL
+#endif
+
+#define MAX_PEAK_CHANNELS 128
+typedef unsigned short oss_peaks_t[MAX_PEAK_CHANNELS];
+#define SNDCTL_DSP_GETIPEAKS __SIOR('P', 43, oss_peaks_t)
+#define SNDCTL_DSP_GETOPEAKS __SIOR('P', 44, oss_peaks_t)
+
+#define SNDCTL_DSP_POLICY __SIOW('P', 45, int) /* See the manual */
+
+/*
+ ****************************************************************************
+ * Few ioctl calls that are not official parts of OSS. They have been used
+ * by few freeware implementations of OSS.
+ */
+#define SNDCTL_DSP_GETCHANNELMASK __SIOWR('P', 64, int)
+#define SNDCTL_DSP_BIND_CHANNEL __SIOWR('P', 65, int)
+# define DSP_BIND_QUERY 0x00000000
+# define DSP_BIND_FRONT 0x00000001
+# define DSP_BIND_SURR 0x00000002
+# define DSP_BIND_CENTER_LFE 0x00000004
+# define DSP_BIND_HANDSET 0x00000008
+# define DSP_BIND_MIC 0x00000010
+# define DSP_BIND_MODEM1 0x00000020
+# define DSP_BIND_MODEM2 0x00000040
+# define DSP_BIND_I2S 0x00000080
+# define DSP_BIND_SPDIF 0x00000100
+# define DSP_BIND_REAR 0x00000200
+
+#ifdef sun
+/* Not part of OSS. Reserved for internal use by Solaris */
+#define X_SADA_GET_PLAYTGT_MASK __SIOR ('P', 66, int)
+#define X_SADA_GET_PLAYTGT __SIOR ('P', 67, int)
+#define X_SADA_SET_PLAYTGT __SIOWR('P', 68, int)
+#endif
+
+#ifndef NO_LEGACY_MIXER
+/*
+ ****************************************************************************
+ * IOCTL commands for the "legacy " /dev/mixer API (obsolete)
+ *
+ * Mixer controls
+ *
+ * There can be up to 20 different analog mixer channels. The
+ * SOUND_MIXER_NRDEVICES gives the currently supported maximum.
+ * The SOUND_MIXER_READ_DEVMASK returns a bitmask which tells
+ * the devices supported by the particular mixer.
+ *
+ * {!notice This "legacy" mixer API is obsolete. It has been superceded
+ * by a new one (see below).
+ */
+
+#define SOUND_MIXER_NRDEVICES 28
+#define SOUND_MIXER_VOLUME 0
+#define SOUND_MIXER_BASS 1
+#define SOUND_MIXER_TREBLE 2
+#define SOUND_MIXER_SYNTH 3
+#define SOUND_MIXER_PCM 4
+#define SOUND_MIXER_SPEAKER 5
+#define SOUND_MIXER_LINE 6
+#define SOUND_MIXER_MIC 7
+#define SOUND_MIXER_CD 8
+#define SOUND_MIXER_IMIX 9 /* Recording monitor */
+#define SOUND_MIXER_ALTPCM 10
+#define SOUND_MIXER_RECLEV 11 /* Recording level */
+#define SOUND_MIXER_IGAIN 12 /* Input gain */
+#define SOUND_MIXER_OGAIN 13 /* Output gain */
+/*
+ * Some soundcards have three line level inputs (line, aux1 and aux2).
+ * Since each card manufacturer has assigned different meanings to
+ * these inputs, it's impractical to assign specific meanings
+ * (eg line, cd, synth etc.) to them.
+ */
+#define SOUND_MIXER_LINE1 14 /* Input source 1 (aux1) */
+#define SOUND_MIXER_LINE2 15 /* Input source 2 (aux2) */
+#define SOUND_MIXER_LINE3 16 /* Input source 3 (line) */
+#define SOUND_MIXER_DIGITAL1 17 /* Digital I/O 1 */
+#define SOUND_MIXER_DIGITAL2 18 /* Digital I/O 2 */
+#define SOUND_MIXER_DIGITAL3 19 /* Digital I/O 3 */
+#define SOUND_MIXER_PHONE 20 /* Phone */
+#define SOUND_MIXER_MONO 21 /* Mono Output */
+#define SOUND_MIXER_VIDEO 22 /* Video/TV (audio) in */
+#define SOUND_MIXER_RADIO 23 /* Radio in */
+#define SOUND_MIXER_DEPTH 24 /* Surround depth */
+#define SOUND_MIXER_REARVOL 25 /* Rear/Surround speaker vol */
+#define SOUND_MIXER_CENTERVOL 26 /* Center/LFE speaker vol */
+#define SOUND_MIXER_SIDEVOL 27 /* Side-Surround (8speaker) vol */
+
+/*
+ * Warning: SOUND_MIXER_SURRVOL is an old name of SOUND_MIXER_SIDEVOL.
+ * They are both assigned to the same mixer control. Don't
+ * use both control names in the same program/driver.
+ */
+#define SOUND_MIXER_SURRVOL SOUND_MIXER_SIDEVOL
+
+/* Some on/off settings (SOUND_SPECIAL_MIN - SOUND_SPECIAL_MAX) */
+/* Not counted to SOUND_MIXER_NRDEVICES, but use the same number space */
+#define SOUND_ONOFF_MIN 28
+#define SOUND_ONOFF_MAX 30
+
+/* Note! Number 31 cannot be used since the sign bit is reserved */
+#define SOUND_MIXER_NONE 31
+
+/*
+ * The following unsupported macros are no longer functional.
+ * Use SOUND_MIXER_PRIVATE# macros in future.
+ */
+#define SOUND_MIXER_ENHANCE SOUND_MIXER_NONE
+#define SOUND_MIXER_MUTE SOUND_MIXER_NONE
+#define SOUND_MIXER_LOUD SOUND_MIXER_NONE
+
+#define SOUND_DEVICE_LABELS \
+ {"Vol ", "Bass ", "Treble", "Synth", "Pcm ", "Speaker ", "Line ", \
+ "Mic ", "CD ", "Mix ", "Pcm2 ", "Rec ", "IGain", "OGain", \
+ "Aux1", "Aux2", "Aux3", "Digital1", "Digital2", "Digital3", \
+ "Phone", "Mono", "Video", "Radio", "Depth", \
+ "Rear", "Center", "Side"}
+
+#define SOUND_DEVICE_NAMES \
+ {"vol", "bass", "treble", "synth", "pcm", "speaker", "line", \
+ "mic", "cd", "mix", "pcm2", "rec", "igain", "ogain", \
+ "aux1", "aux2", "aux3", "dig1", "dig2", "dig3", \
+ "phone", "mono", "video", "radio", "depth", \
+ "rear", "center", "side"}
+
+/* Device bitmask identifiers */
+
+#define SOUND_MIXER_RECSRC 0xff /* Arg contains a bit for each recording source */
+#define SOUND_MIXER_DEVMASK 0xfe /* Arg contains a bit for each supported device */
+#define SOUND_MIXER_RECMASK 0xfd /* Arg contains a bit for each supported recording source */
+#define SOUND_MIXER_CAPS 0xfc
+# define SOUND_CAP_EXCL_INPUT 0x00000001 /* Only one recording source at a time */
+# define SOUND_CAP_NOLEGACY 0x00000004 /* For internal use only */
+# define SOUND_CAP_NORECSRC 0x00000008
+#define SOUND_MIXER_STEREODEVS 0xfb /* Mixer channels supporting stereo */
+
+/* OSS/Free ONLY */
+#define SOUND_MIXER_OUTSRC 0xfa /* Arg contains a bit for each input source to output */
+#define SOUND_MIXER_OUTMASK 0xf9 /* Arg contains a bit for each supported input source to output */
+/* OSS/Free ONLY */
+
+/* Device mask bits */
+
+#define SOUND_MASK_VOLUME (1 << SOUND_MIXER_VOLUME)
+#define SOUND_MASK_BASS (1 << SOUND_MIXER_BASS)
+#define SOUND_MASK_TREBLE (1 << SOUND_MIXER_TREBLE)
+#define SOUND_MASK_SYNTH (1 << SOUND_MIXER_SYNTH)
+#define SOUND_MASK_PCM (1 << SOUND_MIXER_PCM)
+#define SOUND_MASK_SPEAKER (1 << SOUND_MIXER_SPEAKER)
+#define SOUND_MASK_LINE (1 << SOUND_MIXER_LINE)
+#define SOUND_MASK_MIC (1 << SOUND_MIXER_MIC)
+#define SOUND_MASK_CD (1 << SOUND_MIXER_CD)
+#define SOUND_MASK_IMIX (1 << SOUND_MIXER_IMIX)
+#define SOUND_MASK_ALTPCM (1 << SOUND_MIXER_ALTPCM)
+#define SOUND_MASK_RECLEV (1 << SOUND_MIXER_RECLEV)
+#define SOUND_MASK_IGAIN (1 << SOUND_MIXER_IGAIN)
+#define SOUND_MASK_OGAIN (1 << SOUND_MIXER_OGAIN)
+#define SOUND_MASK_LINE1 (1 << SOUND_MIXER_LINE1)
+#define SOUND_MASK_LINE2 (1 << SOUND_MIXER_LINE2)
+#define SOUND_MASK_LINE3 (1 << SOUND_MIXER_LINE3)
+#define SOUND_MASK_DIGITAL1 (1 << SOUND_MIXER_DIGITAL1)
+#define SOUND_MASK_DIGITAL2 (1 << SOUND_MIXER_DIGITAL2)
+#define SOUND_MASK_DIGITAL3 (1 << SOUND_MIXER_DIGITAL3)
+#define SOUND_MASK_MONO (1 << SOUND_MIXER_MONO)
+#define SOUND_MASK_PHONE (1 << SOUND_MIXER_PHONE)
+#define SOUND_MASK_RADIO (1 << SOUND_MIXER_RADIO)
+#define SOUND_MASK_VIDEO (1 << SOUND_MIXER_VIDEO)
+#define SOUND_MASK_DEPTH (1 << SOUND_MIXER_DEPTH)
+#define SOUND_MASK_REARVOL (1 << SOUND_MIXER_REARVOL)
+#define SOUND_MASK_CENTERVOL (1 << SOUND_MIXER_CENTERVOL)
+#define SOUND_MASK_SIDEVOL (1 << SOUND_MIXER_SIDEVOL)
+
+/* Note! SOUND_MASK_SURRVOL is alias of SOUND_MASK_SIDEVOL */
+#define SOUND_MASK_SURRVOL (1 << SOUND_MIXER_SIDEVOL)
+
+/* Obsolete macros */
+#define SOUND_MASK_MUTE (1 << SOUND_MIXER_MUTE)
+#define SOUND_MASK_ENHANCE (1 << SOUND_MIXER_ENHANCE)
+#define SOUND_MASK_LOUD (1 << SOUND_MIXER_LOUD)
+
+#define MIXER_READ(dev) __SIOR('M', dev, int)
+#define SOUND_MIXER_READ_VOLUME MIXER_READ(SOUND_MIXER_VOLUME)
+#define SOUND_MIXER_READ_BASS MIXER_READ(SOUND_MIXER_BASS)
+#define SOUND_MIXER_READ_TREBLE MIXER_READ(SOUND_MIXER_TREBLE)
+#define SOUND_MIXER_READ_SYNTH MIXER_READ(SOUND_MIXER_SYNTH)
+#define SOUND_MIXER_READ_PCM MIXER_READ(SOUND_MIXER_PCM)
+#define SOUND_MIXER_READ_SPEAKER MIXER_READ(SOUND_MIXER_SPEAKER)
+#define SOUND_MIXER_READ_LINE MIXER_READ(SOUND_MIXER_LINE)
+#define SOUND_MIXER_READ_MIC MIXER_READ(SOUND_MIXER_MIC)
+#define SOUND_MIXER_READ_CD MIXER_READ(SOUND_MIXER_CD)
+#define SOUND_MIXER_READ_IMIX MIXER_READ(SOUND_MIXER_IMIX)
+#define SOUND_MIXER_READ_ALTPCM MIXER_READ(SOUND_MIXER_ALTPCM)
+#define SOUND_MIXER_READ_RECLEV MIXER_READ(SOUND_MIXER_RECLEV)
+#define SOUND_MIXER_READ_IGAIN MIXER_READ(SOUND_MIXER_IGAIN)
+#define SOUND_MIXER_READ_OGAIN MIXER_READ(SOUND_MIXER_OGAIN)
+#define SOUND_MIXER_READ_LINE1 MIXER_READ(SOUND_MIXER_LINE1)
+#define SOUND_MIXER_READ_LINE2 MIXER_READ(SOUND_MIXER_LINE2)
+#define SOUND_MIXER_READ_LINE3 MIXER_READ(SOUND_MIXER_LINE3)
+
+/* Obsolete macros */
+#define SOUND_MIXER_READ_MUTE MIXER_READ(SOUND_MIXER_MUTE)
+#define SOUND_MIXER_READ_ENHANCE MIXER_READ(SOUND_MIXER_ENHANCE)
+#define SOUND_MIXER_READ_LOUD MIXER_READ(SOUND_MIXER_LOUD)
+
+#define SOUND_MIXER_READ_RECSRC MIXER_READ(SOUND_MIXER_RECSRC)
+#define SOUND_MIXER_READ_DEVMASK MIXER_READ(SOUND_MIXER_DEVMASK)
+#define SOUND_MIXER_READ_RECMASK MIXER_READ(SOUND_MIXER_RECMASK)
+#define SOUND_MIXER_READ_STEREODEVS MIXER_READ(SOUND_MIXER_STEREODEVS)
+#define SOUND_MIXER_READ_CAPS MIXER_READ(SOUND_MIXER_CAPS)
+
+#define MIXER_WRITE(dev) __SIOWR('M', dev, int)
+#define SOUND_MIXER_WRITE_VOLUME MIXER_WRITE(SOUND_MIXER_VOLUME)
+#define SOUND_MIXER_WRITE_BASS MIXER_WRITE(SOUND_MIXER_BASS)
+#define SOUND_MIXER_WRITE_TREBLE MIXER_WRITE(SOUND_MIXER_TREBLE)
+#define SOUND_MIXER_WRITE_SYNTH MIXER_WRITE(SOUND_MIXER_SYNTH)
+#define SOUND_MIXER_WRITE_PCM MIXER_WRITE(SOUND_MIXER_PCM)
+#define SOUND_MIXER_WRITE_SPEAKER MIXER_WRITE(SOUND_MIXER_SPEAKER)
+#define SOUND_MIXER_WRITE_LINE MIXER_WRITE(SOUND_MIXER_LINE)
+#define SOUND_MIXER_WRITE_MIC MIXER_WRITE(SOUND_MIXER_MIC)
+#define SOUND_MIXER_WRITE_CD MIXER_WRITE(SOUND_MIXER_CD)
+#define SOUND_MIXER_WRITE_IMIX MIXER_WRITE(SOUND_MIXER_IMIX)
+#define SOUND_MIXER_WRITE_ALTPCM MIXER_WRITE(SOUND_MIXER_ALTPCM)
+#define SOUND_MIXER_WRITE_RECLEV MIXER_WRITE(SOUND_MIXER_RECLEV)
+#define SOUND_MIXER_WRITE_IGAIN MIXER_WRITE(SOUND_MIXER_IGAIN)
+#define SOUND_MIXER_WRITE_OGAIN MIXER_WRITE(SOUND_MIXER_OGAIN)
+#define SOUND_MIXER_WRITE_LINE1 MIXER_WRITE(SOUND_MIXER_LINE1)
+#define SOUND_MIXER_WRITE_LINE2 MIXER_WRITE(SOUND_MIXER_LINE2)
+#define SOUND_MIXER_WRITE_LINE3 MIXER_WRITE(SOUND_MIXER_LINE3)
+
+/* Obsolete macros */
+#define SOUND_MIXER_WRITE_MUTE MIXER_WRITE(SOUND_MIXER_MUTE)
+#define SOUND_MIXER_WRITE_ENHANCE MIXER_WRITE(SOUND_MIXER_ENHANCE)
+#define SOUND_MIXER_WRITE_LOUD MIXER_WRITE(SOUND_MIXER_LOUD)
+
+#define SOUND_MIXER_WRITE_RECSRC MIXER_WRITE(SOUND_MIXER_RECSRC)
+
+typedef struct mixer_info /* OBSOLETE */
+{
+ char id[16];
+ char name[32];
+ int modify_counter;
+ int card_number;
+ int port_number;
+ char handle[32];
+} mixer_info;
+
+/* SOUND_MIXER_INFO is obsolete - use SNDCTL_MIXERINFO instead */
+#define SOUND_MIXER_INFO __SIOR ('M', 101, mixer_info)
+
+/*
+ * Two ioctls for special souncard function (OSS/Free only)
+ */
+#define SOUND_MIXER_AGC _SIOWR('M', 103, int)
+#define SOUND_MIXER_3DSE _SIOWR('M', 104, int)
+/*
+ * The SOUND_MIXER_PRIVATE# commands can be redefined by low level drivers.
+ * These features can be used when accessing device specific features.
+ */
+#define SOUND_MIXER_PRIVATE1 __SIOWR('M', 111, int)
+#define SOUND_MIXER_PRIVATE2 __SIOWR('M', 112, int)
+#define SOUND_MIXER_PRIVATE3 __SIOWR('M', 113, int)
+#define SOUND_MIXER_PRIVATE4 __SIOWR('M', 114, int)
+#define SOUND_MIXER_PRIVATE5 __SIOWR('M', 115, int)
+
+/* The following two controls were never implemented and they should not be used. */
+#define SOUND_MIXER_READ_MAINVOL __SIOR ('M', 116, int)
+#define SOUND_MIXER_WRITE_MAINVOL __SIOWR('M', 116, int)
+
+/*
+ * SOUND_MIXER_GETLEVELS and SOUND_MIXER_SETLEVELS calls can be used
+ * for querying current mixer settings from the driver and for loading
+ * default volume settings _prior_ activating the mixer (loading
+ * doesn't affect current state of the mixer hardware). These calls
+ * are for internal use by the driver software only.
+ */
+
+typedef struct mixer_vol_table
+{
+ int num; /* Index to volume table */
+ char name[32];
+ int levels[32];
+} mixer_vol_table;
+
+#define SOUND_MIXER_GETLEVELS __SIOWR('M', 116, mixer_vol_table)
+#define SOUND_MIXER_SETLEVELS __SIOWR('M', 117, mixer_vol_table)
+
+#define OSS_GETVERSION __SIOR ('M', 118, int)
+
+/*
+ * Calls to set/get the recording gain for the currently active
+ * recording source. These calls automatically map to the right control.
+ * Note that these calls are not supported by all drivers. In this case
+ * the call will return -1 with errno set to EINVAL
+ *
+ * The _MONGAIN work in similar way but set/get the monitoring gain for
+ * the currently selected recording source.
+ */
+#define SOUND_MIXER_READ_RECGAIN __SIOR ('M', 119, int)
+#define SOUND_MIXER_WRITE_RECGAIN __SIOWR('M', 119, int)
+#define SOUND_MIXER_READ_MONGAIN __SIOR ('M', 120, int)
+#define SOUND_MIXER_WRITE_MONGAIN __SIOWR('M', 120, int)
+
+/* The following call is for driver development time purposes. It's not
+ * present in any released drivers.
+ */
+typedef unsigned char oss_reserved_t[512];
+#define SOUND_MIXER_RESERVED __SIOWR('M', 121, oss_reserved_t)
+#endif /* ifndef NO_LEGACY_MIXER */
+
+/*
+ *************************************************************************
+ * The "new" mixer API of OSS 4.0 and later.
+ *
+ * This improved mixer API makes it possible to access every possible feature
+ * of every possible device. However you should read the mixer programming
+ * section of the OSS API Developer's Manual. There is no chance that you
+ * could use this interface correctly just by examining this header.
+ */
+
+typedef struct oss_sysinfo
+{
+ char product[32]; /* For example OSS/Free, OSS/Linux or OSS/Solaris */
+ char version[32]; /* For example 4.0a */
+ int versionnum; /* See OSS_GETVERSION */
+ char options[128]; /* Reserved */
+
+ int numaudios; /* # of audio/dsp devices */
+ int openedaudio[8]; /* Bit mask telling which audio devices are busy */
+
+ int numsynths; /* # of availavle synth devices */
+ int nummidis; /* # of available MIDI ports */
+ int numtimers; /* # of available timer devices */
+ int nummixers; /* # of mixer devices */
+
+ int openedmidi[8]; /* Bit mask telling which midi devices are busy */
+ int numcards; /* Number of sound cards in the system */
+ int numaudioengines; /* Number of audio engines in the system */
+ char license[16]; /* For example "GPL" or "CDDL" */
+ int filler[236]; /* For future expansion (set to -1) */
+} oss_sysinfo;
+
+typedef struct oss_mixext
+{
+ int dev; /* Mixer device number */
+ int ctrl; /* Controller number */
+ int type; /* Entry type */
+# define MIXT_DEVROOT 0 /* Device root entry */
+# define MIXT_GROUP 1 /* Controller group */
+# define MIXT_ONOFF 2 /* OFF (0) or ON (1) */
+# define MIXT_ENUM 3 /* Enumerated (0 to maxvalue) */
+# define MIXT_MONOSLIDER 4 /* Mono slider (0 to 255) */
+# define MIXT_STEREOSLIDER 5 /* Stereo slider (dual 0 to 255) */
+# define MIXT_MESSAGE 6 /* (Readable) textual message */
+# define MIXT_MONOVU 7 /* VU meter value (mono) */
+# define MIXT_STEREOVU 8 /* VU meter value (stereo) */
+# define MIXT_MONOPEAK 9 /* VU meter peak value (mono) */
+# define MIXT_STEREOPEAK 10 /* VU meter peak value (stereo) */
+# define MIXT_RADIOGROUP 11 /* Radio button group */
+# define MIXT_MARKER 12 /* Separator between normal and extension entries */
+# define MIXT_VALUE 13 /* Decimal value entry */
+# define MIXT_HEXVALUE 14 /* Hexadecimal value entry */
+# define MIXT_MONODB 15 /* OBSOLETE */
+# define MIXT_STEREODB 16 /* OBSOLETE */
+# define MIXT_SLIDER 17 /* Slider (mono) with full (31 bit) postitive integer range */
+# define MIXT_3D 18
+
+/*
+ * Sliders with range expanded to 15 bits per channel (0-32767)
+ */
+# define MIXT_MONOSLIDER16 19
+# define MIXT_STEREOSLIDER16 20
+# define MIXT_MUTE 21 /* Mute=1, unmute=0 */
+
+ /**************************************************************/
+
+ /* Possible value range (minvalue to maxvalue) */
+ /* Note that maxvalue may also be smaller than minvalue */
+ int maxvalue;
+ int minvalue;
+
+ int flags;
+# define MIXF_READABLE 0x00000001 /* Has readable value */
+# define MIXF_WRITEABLE 0x00000002 /* Has writeable value */
+# define MIXF_POLL 0x00000004 /* May change itself */
+# define MIXF_HZ 0x00000008 /* Herz scale */
+# define MIXF_STRING 0x00000010 /* Use dynamic extensions for value */
+# define MIXF_DYNAMIC 0x00000010 /* Supports dynamic extensions */
+# define MIXF_OKFAIL 0x00000020 /* Interpret value as 1=OK, 0=FAIL */
+# define MIXF_FLAT 0x00000040 /* Flat vertical space requirements */
+# define MIXF_LEGACY 0x00000080 /* Legacy mixer control group */
+# define MIXF_CENTIBEL 0x00000100 /* Centibel (0.1 dB) step size */
+# define MIXF_DECIBEL 0x00000200 /* Step size of 1 dB */
+# define MIXF_MAINVOL 0x00000400 /* Main volume control */
+# define MIXF_PCMVOL 0x00000800 /* PCM output volume control */
+# define MIXF_RECVOL 0x00001000 /* PCM recording volume control */
+# define MIXF_MONVOL 0x00002000 /* Input->output monitor volume */
+# define MIXF_WIDE 0x00004000 /* Enum control has wide labels */
+# define MIXF_DESCR 0x00008000 /* Description (tooltip) available */
+ char id[16]; /* Mnemonic ID (mainly for internal use) */
+ int parent; /* Entry# of parent (group) node (-1 if root) */
+
+ int dummy; /* Internal use */
+
+ int timestamp;
+
+ char data[64]; /* Misc data (entry type dependent) */
+ unsigned char enum_present[32]; /* Mask of allowed enum values */
+ int control_no; /* SOUND_MIXER_VOLUME..SOUND_MIXER_MIDI */
+ /* (-1 means not indicated) */
+
+/*
+ * The desc field is reserved for internal purposes of OSS. It should not be
+ * used by applications.
+ */
+ unsigned int desc;
+#define MIXEXT_SCOPE_MASK 0x0000003f
+#define MIXEXT_SCOPE_OTHER 0x00000000
+#define MIXEXT_SCOPE_INPUT 0x00000001
+#define MIXEXT_SCOPE_OUTPUT 0x00000002
+#define MIXEXT_SCOPE_MONITOR 0x00000003
+#define MIXEXT_SCOPE_RECSWITCH 0x00000004
+
+ char extname[32];
+ int update_counter;
+ int rgbcolor; /* 0 means default color (not black) . Otherwise 24 bit RGB color */
+ int filler[6];
+} oss_mixext;
+
+/*
+ * Recommended colors to be used in the rgbcolor field. These match the
+ * colors used as the audio jack colors in HD audio motherboards.
+ */
+#define OSS_RGB_BLUE 0x7aabde // Light blue
+#define OSS_RGB_GREEN 0xb3c98c // Lime green
+#define OSS_RGB_PINK 0xe88c99
+#define OSS_RGB_GRAY 0xd1ccc4
+#define OSS_RGB_BLACK 0x2b2926 // Light black
+#define OSS_RGB_ORANGE 0xe89e47
+#define OSS_RGB_RED 0xff0000
+#define OSS_RGB_YELLOW 0xffff00
+#define OSS_RGB_PURPLE 0x800080
+#define OSS_RGB_WHITE 0xf8f8ff
+
+typedef struct oss_mixext_root
+{
+ char id[16];
+ char name[48];
+} oss_mixext_root;
+
+typedef struct oss_mixer_value
+{
+ int dev;
+ int ctrl;
+ int value;
+ int flags; /* Reserved for future use. Initialize to 0 */
+ int timestamp; /* Must be set to oss_mixext.timestamp */
+ int filler[8]; /* Reserved for future use. Initialize to 0 */
+} oss_mixer_value;
+
+#define OSS_ENUM_MAXVALUE 255
+#define OSS_ENUM_STRINGSIZE 3000
+typedef struct oss_mixer_enuminfo
+{
+ int dev;
+ int ctrl;
+ int nvalues;
+ int version; /* Read the manual */
+ short strindex[OSS_ENUM_MAXVALUE];
+ char strings[OSS_ENUM_STRINGSIZE];
+} oss_mixer_enuminfo;
+
+#define OPEN_READ PCM_ENABLE_INPUT
+#define OPEN_WRITE PCM_ENABLE_OUTPUT
+#define OPEN_READWRITE (OPEN_READ|OPEN_WRITE)
+
+typedef struct oss_audioinfo
+{
+ int dev; /* Audio device number */
+ char name[64];
+ int busy; /* 0, OPEN_READ, OPEN_WRITE or OPEN_READWRITE */
+ int pid;
+ int caps; /* PCM_CAP_INPUT, PCM_CAP_OUTPUT */
+ int iformats, oformats;
+ int magic; /* Reserved for internal use */
+ char cmd[64]; /* Command using the device (if known) */
+ int card_number;
+ int port_number;
+ int mixer_dev;
+ int legacy_device; /* Obsolete field. Replaced by devnode */
+ int enabled; /* 1=enabled, 0=device not ready at this moment */
+ int flags; /* For internal use only - no practical meaning */
+ int min_rate, max_rate; /* Sample rate limits */
+ int min_channels, max_channels; /* Number of channels supported */
+ int binding; /* DSP_BIND_FRONT, etc. 0 means undefined */
+ int rate_source;
+ char handle[32];
+#define OSS_MAX_SAMPLE_RATES 20 /* Cannot be changed */
+ unsigned int nrates, rates[OSS_MAX_SAMPLE_RATES]; /* Please read the manual before using these */
+ oss_longname_t song_name; /* Song name (if given) */
+ oss_label_t label; /* Device label (if given) */
+ int latency; /* In usecs, -1=unknown */
+ oss_devnode_t devnode; /* Device special file name (absolute path) */
+ int next_play_engine; /* Read the documentation for more info */
+ int next_rec_engine; /* Read the documentation for more info */
+ int filler[184];
+} oss_audioinfo;
+
+typedef struct oss_mixerinfo
+{
+ int dev;
+ char id[16];
+ char name[32];
+ int modify_counter;
+ int card_number;
+ int port_number;
+ char handle[32];
+ int magic; /* Reserved */
+ int enabled; /* Reserved */
+ int caps;
+#define MIXER_CAP_VIRTUAL 0x00000001
+#define MIXER_CAP_LAYOUT_B 0x00000002 /* For internal use only */
+#define MIXER_CAP_NARROW 0x00000004 /* Conserve horiz space */
+ int flags; /* Reserved */
+ int nrext;
+ /*
+ * The priority field can be used to select the default (motherboard)
+ * mixer device. The mixer with the highest priority is the
+ * most preferred one. -2 or less means that this device cannot be used
+ * as the default mixer.
+ */
+ int priority;
+ oss_devnode_t devnode; /* Device special file name (absolute path) */
+ int legacy_device;
+ int filler[245]; /* Reserved */
+} oss_mixerinfo;
+
+typedef struct oss_midi_info
+{
+ int dev; /* Midi device number */
+ char name[64];
+ int busy; /* 0, OPEN_READ, OPEN_WRITE or OPEN_READWRITE */
+ int pid;
+ char cmd[64]; /* Command using the device (if known) */
+ int caps;
+#define MIDI_CAP_MPU401 0x00000001 /**** OBSOLETE ****/
+#define MIDI_CAP_INPUT 0x00000002
+#define MIDI_CAP_OUTPUT 0x00000004
+#define MIDI_CAP_INOUT (MIDI_CAP_INPUT|MIDI_CAP_OUTPUT)
+#define MIDI_CAP_VIRTUAL 0x00000008 /* Pseudo device */
+#define MIDI_CAP_MTCINPUT 0x00000010 /* Supports SNDCTL_MIDI_MTCINPUT */
+#define MIDI_CAP_CLIENT 0x00000020 /* Virtual client side device */
+#define MIDI_CAP_SERVER 0x00000040 /* Virtual server side device */
+#define MIDI_CAP_INTERNAL 0x00000080 /* Internal (synth) device */
+#define MIDI_CAP_EXTERNAL 0x00000100 /* external (MIDI port) device */
+#define MIDI_CAP_PTOP 0x00000200 /* Point to point link to one device */
+#define MIDI_CAP_MTC 0x00000400 /* MTC/SMPTE (control) device */
+ int magic; /* Reserved for internal use */
+ int card_number;
+ int port_number;
+ int enabled; /* 1=enabled, 0=device not ready at this moment */
+ int flags; /* For internal use only - no practical meaning */
+ char handle[32];
+ oss_longname_t song_name; /* Song name (if known) */
+ oss_label_t label; /* Device label (if given) */
+ int latency; /* In usecs, -1=unknown */
+ oss_devnode_t devnode; /* Device special file name (absolute path) */
+ int legacy_device; /* Legacy device mapping */
+ int filler[235];
+} oss_midi_info;
+
+typedef struct oss_card_info
+{
+ int card;
+ char shortname[16];
+ char longname[128];
+ int flags;
+ char hw_info[400];
+ int intr_count, ack_count;
+ int filler[154];
+} oss_card_info;
+
+#define SNDCTL_SYSINFO __SIOR ('X', 1, oss_sysinfo)
+#define OSS_SYSINFO SNDCTL_SYSINFO /* Old name */
+
+#define SNDCTL_MIX_NRMIX __SIOR ('X', 2, int)
+#define SNDCTL_MIX_NREXT __SIOWR('X', 3, int)
+#define SNDCTL_MIX_EXTINFO __SIOWR('X', 4, oss_mixext)
+#define SNDCTL_MIX_READ __SIOWR('X', 5, oss_mixer_value)
+#define SNDCTL_MIX_WRITE __SIOWR('X', 6, oss_mixer_value)
+
+#define SNDCTL_AUDIOINFO __SIOWR('X', 7, oss_audioinfo)
+#define SNDCTL_MIX_ENUMINFO __SIOWR('X', 8, oss_mixer_enuminfo)
+#define SNDCTL_MIDIINFO __SIOWR('X', 9, oss_midi_info)
+#define SNDCTL_MIXERINFO __SIOWR('X',10, oss_mixerinfo)
+#define SNDCTL_CARDINFO __SIOWR('X',11, oss_card_info)
+#define SNDCTL_ENGINEINFO __SIOWR('X',12, oss_audioinfo)
+#define SNDCTL_AUDIOINFO_EX __SIOWR('X',13, oss_audioinfo)
+
+#define SNDCTL_MIX_DESCRIPTION __SIOWR('X',14, oss_mixer_enuminfo)
+
+/* ioctl codes 'X', 200-255 are reserved for internal use */
+
+/*
+ * Few more "globally" available ioctl calls.
+ */
+#define SNDCTL_SETSONG __SIOW ('Y', 2, oss_longname_t)
+#define SNDCTL_GETSONG __SIOR ('Y', 2, oss_longname_t)
+#define SNDCTL_SETNAME __SIOW ('Y', 3, oss_longname_t)
+#define SNDCTL_SETLABEL __SIOW ('Y', 4, oss_label_t)
+#define SNDCTL_GETLABEL __SIOR ('Y', 4, oss_label_t)
+/*
+ * The "new" mixer API definitions end here.
+ ***************************************
+ */
+
+/*
+ *********************************************************
+ * Few routines that are included in -lOSSlib
+ *
+ * At this moment this interface is not used. OSSlib contains just
+ * stubs that call the related system calls directly.
+ */
+#ifdef OSSLIB
+extern int osslib_open (const char *path, int flags, int dummy);
+extern void osslib_close (int fd);
+extern int osslib_write (int fd, const void *buf, int count);
+extern int osslib_read (int fd, void *buf, int count);
+extern int osslib_ioctl (int fd, unsigned int request, void *arg);
+#else
+# define osslib_open open
+# define osslib_close close
+# define osslib_write write
+# define osslib_read read
+# define osslib_ioctl ioctl
+#endif
+
+#if 1
+#define SNDCTL_DSP_NONBLOCK __SIO ('P',14) /* Obsolete. Not supported any more */
+#endif
+
+#if 1
+/*
+ * Some obsolete macros that are not part of Open Sound System API.
+ */
+#define SOUND_PCM_READ_RATE SOUND_PCM_READ_RATE_is_obsolete
+#define SOUND_PCM_READ_BITS SOUND_PCM_READ_BITS_is_obsolete
+#define SOUND_PCM_READ_CHANNELS SOUND_PCM_READ_CHANNELS_is_obsolete
+#define SOUND_PCM_WRITE_RATE SOUND_PCM_WRITE_RATE_is_obsolet_use_SNDCTL_DSP_SPEED_instead
+#define SOUND_PCM_WRITE_CHANNELS SOUND_PCM_WRITE_CHANNELS_is_obsolete_use_SNDCTL_DSP_CHANNELS_instead
+#define SOUND_PCM_WRITE_BITS SOUND_PCM_WRITE_BITS_is_obsolete_use_SNDCTL_DSP_SETFMT_instead
+#define SOUND_PCM_POST SOUND_PCM_POST_is_obsolete_use_SNDCTL_DSP_POST_instead
+#define SOUND_PCM_RESET SOUND_PCM_RESET_is_obsolete_use_SNDCTL_DSP_HALT_instead
+#define SOUND_PCM_SYNC SOUND_PCM_SYNC_is_obsolete_use_SNDCTL_DSP_SYNC_instead
+#define SOUND_PCM_SUBDIVIDE SOUND_PCM_SUBDIVIDE_is_obsolete_use_SNDCTL_DSP_SUBDIVIDE_instead
+#define SOUND_PCM_SETFRAGMENT SOUND_PCM_SETFRAGMENT_is_obsolete_use_SNDCTL_DSP_SETFRAGMENT_instead
+#define SOUND_PCM_GETFMTS SOUND_PCM_GETFMTS_is_obsolete_use_SNDCTL_DSP_GETFMTS_instead
+#define SOUND_PCM_SETFMT SOUND_PCM_SETFMT_is_obsolete_use_SNDCTL_DSP_SETFMT_instead
+#define SOUND_PCM_GETOSPACE SOUND_PCM_GETOSPACE_is_obsolete_use_SNDCTL_DSP_GETOSPACE_instead
+#define SOUND_PCM_GETISPACE SOUND_PCM_GETISPACE_is_obsolete_use_SNDCTL_DSP_GETISPACE_instead
+#define SOUND_PCM_NONBLOCK SOUND_PCM_NONBLOCK_is_obsolete_use_SNDCTL_DSP_NONBLOCK_instead
+#define SOUND_PCM_GETCAPS SOUND_PCM_GETCAPS_is_obsolete_use_SNDCTL_DSP_GETCAPS_instead
+#define SOUND_PCM_GETTRIGGER SOUND_PCM_GETTRIGGER_is_obsolete_use_SNDCTL_DSP_GETTRIGGER_instead
+#define SOUND_PCM_SETTRIGGER SOUND_PCM_SETTRIGGER_is_obsolete_use_SNDCTL_DSP_SETTRIGGER_instead
+#define SOUND_PCM_SETSYNCRO SOUND_PCM_SETSYNCRO_is_obsolete_use_SNDCTL_DSP_SETSYNCRO_instead
+#define SOUND_PCM_GETIPTR SOUND_PCM_GETIPTR_is_obsolete_use_SNDCTL_DSP_GETIPTR_instead
+#define SOUND_PCM_GETOPTR SOUND_PCM_GETOPTR_is_obsolete_use_SNDCTL_DSP_GETOPTR_instead
+#define SOUND_PCM_MAPINBUF SOUND_PCM_MAPINBUF_is_obsolete_use_SNDCTL_DSP_MAPINBUF_instead
+#define SOUND_PCM_MAPOUTBUF SOUND_PCM_MAPOUTBUF_is_obsolete_use_SNDCTL_DSP_MAPOUTBUF_instead
+#endif
+
+#endif
diff --git a/sys/oss4/oss4-source.c b/sys/oss4/oss4-source.c
new file mode 100644
index 0000000..eadb4c5
--- /dev/null
+++ b/sys/oss4/oss4-source.c
@@ -0,0 +1,997 @@
+/* GStreamer OSS4 audio source
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+
+/**
+ * SECTION:element-oss4src
+ *
+ * This element lets you record sound using the Open Sound System (OSS)
+ * version 4.
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * |[
+ * gst-launch -v oss4src ! queue ! audioconvert ! vorbisenc ! oggmux ! filesink location=mymusic.ogg
+ * ]| will record sound from your sound card using OSS4 and encode it to an
+ * Ogg/Vorbis file (this will only work if your mixer settings are right
+ * and the right inputs areenabled etc.)
+ * </refsect2>
+ *
+ * Since: 0.10.7
+ */
+
+/* FIXME: make sure we're not doing ioctls from the app thread (e.g. via the
+ * mixer interface) while recording */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gst/interfaces/mixer.h>
+#include <gst/gst-i18n-plugin.h>
+
+#define NO_LEGACY_MIXER
+#include "oss4-audio.h"
+#include "oss4-source.h"
+#include "oss4-property-probe.h"
+#include "oss4-soundcard.h"
+
+#define GST_OSS4_SOURCE_IS_OPEN(src) (GST_OSS4_SOURCE(src)->fd != -1)
+
+GST_DEBUG_CATEGORY_EXTERN (oss4src_debug);
+#define GST_CAT_DEFAULT oss4src_debug
+
+#define DEFAULT_DEVICE NULL
+#define DEFAULT_DEVICE_NAME NULL
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+ PROP_DEVICE_NAME
+};
+
+static void gst_oss4_source_init_interfaces (GType type);
+
+GST_BOILERPLATE_FULL (GstOss4Source, gst_oss4_source, GstAudioSrc,
+ GST_TYPE_AUDIO_SRC, gst_oss4_source_init_interfaces);
+
+static void gst_oss4_source_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static void gst_oss4_source_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+
+static void gst_oss4_source_dispose (GObject * object);
+static void gst_oss4_source_finalize (GstOss4Source * osssrc);
+
+static GstCaps *gst_oss4_source_getcaps (GstBaseSrc * bsrc);
+
+static gboolean gst_oss4_source_open (GstAudioSrc * asrc,
+ gboolean silent_errors);
+static gboolean gst_oss4_source_open_func (GstAudioSrc * asrc);
+static gboolean gst_oss4_source_close (GstAudioSrc * asrc);
+static gboolean gst_oss4_source_prepare (GstAudioSrc * asrc,
+ GstRingBufferSpec * spec);
+static gboolean gst_oss4_source_unprepare (GstAudioSrc * asrc);
+static guint gst_oss4_source_read (GstAudioSrc * asrc, gpointer data,
+ guint length);
+static guint gst_oss4_source_delay (GstAudioSrc * asrc);
+static void gst_oss4_source_reset (GstAudioSrc * asrc);
+
+static void
+gst_oss4_source_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+ GstPadTemplate *templ;
+
+ gst_element_class_set_details_simple (element_class,
+ "OSS v4 Audio Source", "Source/Audio",
+ "Capture from a sound card via OSS version 4",
+ "Tim-Philipp Müller <tim centricular net>");
+
+ templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+ gst_oss4_audio_get_template_caps ());
+ gst_element_class_add_pad_template (element_class, templ);
+ gst_object_unref (templ);
+}
+
+static void
+gst_oss4_source_class_init (GstOss4SourceClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstBaseSrcClass *gstbasesrc_class;
+ GstAudioSrcClass *gstaudiosrc_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstbasesrc_class = (GstBaseSrcClass *) klass;
+ gstaudiosrc_class = (GstAudioSrcClass *) klass;
+
+ gobject_class->dispose = gst_oss4_source_dispose;
+ gobject_class->finalize = (GObjectFinalizeFunc) gst_oss4_source_finalize;
+ gobject_class->get_property = gst_oss4_source_get_property;
+ gobject_class->set_property = gst_oss4_source_set_property;
+
+ gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_oss4_source_getcaps);
+
+ gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_oss4_source_open_func);
+ gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_oss4_source_prepare);
+ gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_oss4_source_unprepare);
+ gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_oss4_source_close);
+ gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_oss4_source_read);
+ gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_oss4_source_delay);
+ gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_oss4_source_reset);
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device",
+ "OSS4 device (e.g. /dev/oss/hdaudio0/pcm0 or /dev/dspN) "
+ "(NULL = use first available device)",
+ DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
+ g_param_spec_string ("device-name", "Device name",
+ "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+gst_oss4_source_init (GstOss4Source * osssrc, GstOss4SourceClass * g_class)
+{
+ const gchar *device;
+
+ device = g_getenv ("AUDIODEV");
+ if (device == NULL)
+ device = DEFAULT_DEVICE;
+
+ osssrc->fd = -1;
+ osssrc->device = g_strdup (device);
+ osssrc->device_name = g_strdup (DEFAULT_DEVICE_NAME);
+ osssrc->device_name = NULL;
+}
+
+static void
+gst_oss4_source_finalize (GstOss4Source * oss)
+{
+ g_free (oss->device);
+ oss->device = NULL;
+
+ g_list_free (oss->property_probe_list);
+ oss->property_probe_list = NULL;
+
+ G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (oss));
+}
+
+static void
+gst_oss4_source_dispose (GObject * object)
+{
+ GstOss4Source *oss = GST_OSS4_SOURCE (object);
+
+ if (oss->probed_caps) {
+ gst_caps_unref (oss->probed_caps);
+ oss->probed_caps = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_oss4_source_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOss4Source *oss;
+
+ oss = GST_OSS4_SOURCE (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ GST_OBJECT_LOCK (oss);
+ if (oss->fd == -1) {
+ g_free (oss->device);
+ oss->device = g_value_dup_string (value);
+ g_free (oss->device_name);
+ oss->device_name = NULL;
+ } else {
+ g_warning ("%s: can't change \"device\" property while audio source "
+ "is open", GST_OBJECT_NAME (oss));
+ }
+ GST_OBJECT_UNLOCK (oss);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_oss4_source_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstOss4Source *oss;
+
+ oss = GST_OSS4_SOURCE (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ GST_OBJECT_LOCK (oss);
+ g_value_set_string (value, oss->device);
+ GST_OBJECT_UNLOCK (oss);
+ break;
+ case PROP_DEVICE_NAME:
+ GST_OBJECT_LOCK (oss);
+ /* If device is set, try to retrieve the name even if we're not open */
+ if (oss->fd == -1 && oss->device != NULL) {
+ if (gst_oss4_source_open (GST_AUDIO_SRC (oss), TRUE)) {
+ g_value_set_string (value, oss->device_name);
+ gst_oss4_source_close (GST_AUDIO_SRC (oss));
+ } else {
+ gchar *name = NULL;
+
+ gst_oss4_property_probe_find_device_name_nofd (GST_OBJECT (oss),
+ oss->device, &name);
+ g_value_set_string (value, name);
+ g_free (name);
+ }
+ } else {
+ g_value_set_string (value, oss->device_name);
+ }
+
+ GST_OBJECT_UNLOCK (oss);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstCaps *
+gst_oss4_source_getcaps (GstBaseSrc * bsrc)
+{
+ GstOss4Source *oss;
+ GstCaps *caps;
+
+ oss = GST_OSS4_SOURCE (bsrc);
+
+ if (oss->fd == -1) {
+ caps = gst_oss4_audio_get_template_caps ();
+ } else if (oss->probed_caps) {
+ caps = gst_caps_copy (oss->probed_caps);
+ } else {
+ caps = gst_oss4_audio_probe_caps (GST_OBJECT (oss), oss->fd);
+ if (caps != NULL && !gst_caps_is_empty (caps)) {
+ oss->probed_caps = gst_caps_copy (caps);
+ }
+ }
+
+ return caps;
+}
+
+/* note: we must not take the object lock here unless we fix up get_property */
+static gboolean
+gst_oss4_source_open (GstAudioSrc * asrc, gboolean silent_errors)
+{
+ GstOss4Source *oss;
+ gchar *device;
+ int mode;
+
+ oss = GST_OSS4_SOURCE (asrc);
+
+ if (oss->device)
+ device = g_strdup (oss->device);
+ else
+ device = gst_oss4_audio_find_device (GST_OBJECT_CAST (oss));
+
+ /* desperate times, desperate measures */
+ if (device == NULL)
+ device = g_strdup ("/dev/dsp0");
+
+ GST_INFO_OBJECT (oss, "Trying to open OSS4 device '%s'", device);
+
+ /* we open in non-blocking mode even if we don't really want to do writes
+ * non-blocking because we can't be sure that this is really a genuine
+ * OSS4 device with well-behaved drivers etc. We really don't want to
+ * hang forever under any circumstances. */
+ oss->fd = open (device, O_RDONLY | O_NONBLOCK, 0);
+ if (oss->fd == -1) {
+ switch (errno) {
+ case EBUSY:
+ goto busy;
+ case EACCES:
+ goto no_permission;
+ default:
+ goto open_failed;
+ }
+ }
+
+ GST_INFO_OBJECT (oss, "Opened device");
+
+ /* Make sure it's OSS4. If it's old OSS, let osssink handle it */
+ if (!gst_oss4_audio_check_version (GST_OBJECT_CAST (oss), oss->fd))
+ goto legacy_oss;
+
+ /* now remove the non-blocking flag. */
+ mode = fcntl (oss->fd, F_GETFL);
+ mode &= ~O_NONBLOCK;
+ if (fcntl (oss->fd, F_SETFL, mode) < 0) {
+ /* some drivers do no support unsetting the non-blocking flag, try to
+ * close/open the device then. This is racy but we error out properly. */
+ GST_WARNING_OBJECT (oss, "failed to unset O_NONBLOCK (buggy driver?), "
+ "will try to re-open device now");
+ gst_oss4_source_close (asrc);
+ if ((oss->fd = open (device, O_RDONLY, 0)) == -1)
+ goto non_block;
+ }
+
+ oss->open_device = device;
+
+ /* not using ENGINEINFO here because it sometimes returns a different and
+ * less useful name than AUDIOINFO for the same device */
+ if (!gst_oss4_property_probe_find_device_name (GST_OBJECT (oss), oss->fd,
+ oss->open_device, &oss->device_name)) {
+ oss->device_name = NULL;
+ }
+
+ return TRUE;
+
+ /* ERRORS */
+busy:
+ {
+ if (!silent_errors) {
+ GST_ELEMENT_ERROR (oss, RESOURCE, BUSY,
+ (_("Could not open audio device for playback. "
+ "Device is being used by another application.")), (NULL));
+ }
+ g_free (device);
+ return FALSE;
+ }
+no_permission:
+ {
+ if (!silent_errors) {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
+ (_("Could not open audio device for playback. "
+ "You don't have permission to open the device.")),
+ GST_ERROR_SYSTEM);
+ }
+ g_free (device);
+ return FALSE;
+ }
+open_failed:
+ {
+ if (!silent_errors) {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
+ (_("Could not open audio device for playback.")), GST_ERROR_SYSTEM);
+ }
+ g_free (device);
+ return FALSE;
+ }
+legacy_oss:
+ {
+ gst_oss4_source_close (asrc);
+ if (!silent_errors) {
+ GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
+ (_("Could not open audio device for playback. "
+ "This version of the Open Sound System is not supported by this "
+ "element.")), ("Try the 'osssink' element instead"));
+ }
+ g_free (device);
+ return FALSE;
+ }
+non_block:
+ {
+ if (!silent_errors) {
+ GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, (NULL),
+ ("Unable to set device %s into non-blocking mode: %s",
+ oss->device, g_strerror (errno)));
+ }
+ g_free (device);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_oss4_source_open_func (GstAudioSrc * asrc)
+{
+ return gst_oss4_source_open (asrc, FALSE);
+}
+
+static void
+gst_oss4_source_free_mixer_tracks (GstOss4Source * oss)
+{
+ g_list_foreach (oss->tracks, (GFunc) g_object_unref, NULL);
+ g_list_free (oss->tracks);
+ oss->tracks = NULL;
+}
+
+static gboolean
+gst_oss4_source_close (GstAudioSrc * asrc)
+{
+ GstOss4Source *oss;
+
+ oss = GST_OSS4_SOURCE (asrc);
+
+ if (oss->fd != -1) {
+ GST_DEBUG_OBJECT (oss, "closing device");
+ close (oss->fd);
+ oss->fd = -1;
+ }
+
+ oss->bytes_per_sample = 0;
+
+ gst_caps_replace (&oss->probed_caps, NULL);
+
+ g_free (oss->open_device);
+ oss->open_device = NULL;
+
+ g_free (oss->device_name);
+ oss->device_name = NULL;
+
+ gst_oss4_source_free_mixer_tracks (oss);
+
+ return TRUE;
+}
+
+static gboolean
+gst_oss4_source_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
+{
+ GstOss4Source *oss;
+
+ oss = GST_OSS4_SOURCE (asrc);
+
+ if (!gst_oss4_audio_set_format (GST_OBJECT_CAST (oss), oss->fd, spec)) {
+ GST_WARNING_OBJECT (oss, "Couldn't set requested format %" GST_PTR_FORMAT,
+ spec->caps);
+ return FALSE;
+ }
+
+ oss->bytes_per_sample = spec->bytes_per_sample;
+ return TRUE;
+}
+
+static gboolean
+gst_oss4_source_unprepare (GstAudioSrc * asrc)
+{
+ /* could do a SNDCTL_DSP_HALT, but the OSS manual recommends a close/open,
+ * since HALT won't properly reset some devices, apparently */
+
+ if (!gst_oss4_source_close (asrc))
+ goto couldnt_close;
+
+ if (!gst_oss4_source_open_func (asrc))
+ goto couldnt_reopen;
+
+ return TRUE;
+
+ /* ERRORS */
+couldnt_close:
+ {
+ GST_DEBUG_OBJECT (asrc, "Couldn't close the audio device");
+ return FALSE;
+ }
+couldnt_reopen:
+ {
+ GST_DEBUG_OBJECT (asrc, "Couldn't reopen the audio device");
+ return FALSE;
+ }
+}
+
+static guint
+gst_oss4_source_read (GstAudioSrc * asrc, gpointer data, guint length)
+{
+ GstOss4Source *oss;
+ int n;
+
+ oss = GST_OSS4_SOURCE_CAST (asrc);
+
+ n = read (oss->fd, data, length);
+ GST_LOG_OBJECT (asrc, "%u bytes, %u samples", n, n / oss->bytes_per_sample);
+
+ if (G_UNLIKELY (n < 0)) {
+ switch (errno) {
+ case ENOTSUP:
+ case EACCES:{
+ /* This is the most likely cause, I think */
+ GST_ELEMENT_ERROR (asrc, RESOURCE, READ,
+ (_("Recording is not supported by this audio device.")),
+ ("read: %s (device: %s) (maybe this is an output-only device?)",
+ g_strerror (errno), oss->open_device));
+ break;
+ }
+ default:{
+ GST_ELEMENT_ERROR (asrc, RESOURCE, READ,
+ (_("Error recording from audio device.")),
+ ("read: %s (device: %s)", g_strerror (errno), oss->open_device));
+ break;
+ }
+ }
+ }
+
+ return (guint) n;
+}
+
+static guint
+gst_oss4_source_delay (GstAudioSrc * asrc)
+{
+ audio_buf_info info = { 0, };
+ GstOss4Source *oss;
+ guint delay;
+
+ oss = GST_OSS4_SOURCE_CAST (asrc);
+
+ if (ioctl (oss->fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
+ GST_LOG_OBJECT (oss, "GETISPACE failed: %s", g_strerror (errno));
+ return 0;
+ }
+
+ delay = (info.fragstotal * info.fragsize) - info.bytes;
+ GST_LOG_OBJECT (oss, "fragstotal:%d, fragsize:%d, bytes:%d, delay:%d",
+ info.fragstotal, info.fragsize, info.bytes, delay);
+ return delay;
+}
+
+static void
+gst_oss4_source_reset (GstAudioSrc * asrc)
+{
+ /* There's nothing we can do here really: OSS can't handle access to the
+ * same device/fd from multiple threads and might deadlock or blow up in
+ * other ways if we try an ioctl SNDCTL_DSP_HALT or similar */
+}
+
+/* GstMixer interface, which we abuse here for input selection, because we
+ * don't have a proper interface for that and because that's what
+ * gnome-sound-recorder does. */
+
+/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */
+G_DEFINE_TYPE (GstOss4SourceInput, gst_oss4_source_input, GST_TYPE_MIXER_TRACK);
+
+static void
+gst_oss4_source_input_class_init (GstOss4SourceInputClass * klass)
+{
+ /* nothing to do here */
+}
+
+static void
+gst_oss4_source_input_init (GstOss4SourceInput * i)
+{
+ /* nothing to do here */
+}
+
+#if 0
+
+static void
+gst_ossmixer_ensure_track_list (GstOssMixer * mixer)
+{
+ gint i, master = -1;
+
+ g_return_if_fail (mixer->fd != -1);
+
+ if (mixer->tracklist)
+ return;
+
+ /* find master volume */
+ if (mixer->devmask & SOUND_MASK_VOLUME)
+ master = SOUND_MIXER_VOLUME;
+ else if (mixer->devmask & SOUND_MASK_PCM)
+ master = SOUND_MIXER_PCM;
+ else if (mixer->devmask & SOUND_MASK_SPEAKER)
+ master = SOUND_MIXER_SPEAKER; /* doubtful... */
+ /* else: no master, so we won't set any */
+
+ /* build track list */
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (mixer->devmask & (1 << i)) {
+ GstMixerTrack *track;
+ gboolean input = FALSE, stereo = FALSE, record = FALSE;
+
+ /* track exists, make up capabilities */
+ if (MASK_BIT_IS_SET (mixer->stereomask, i))
+ stereo = TRUE;
+ if (MASK_BIT_IS_SET (mixer->recmask, i))
+ input = TRUE;
+ if (MASK_BIT_IS_SET (mixer->recdevs, i))
+ record = TRUE;
+
+ /* do we want mixer in our list? */
+ if (!((mixer->dir & GST_OSS_MIXER_CAPTURE && input == TRUE) ||
+ (mixer->dir & GST_OSS_MIXER_PLAYBACK && i != SOUND_MIXER_PCM)))
+ /* the PLAYBACK case seems hacky, but that's how 0.8 had it */
+ continue;
+
+ /* add track to list */
+ track = gst_ossmixer_track_new (mixer->fd, i, stereo ? 2 : 1,
+ (record ? GST_MIXER_TRACK_RECORD : 0) |
+ (input ? GST_MIXER_TRACK_INPUT :
+ GST_MIXER_TRACK_OUTPUT) |
+ ((master != i) ? 0 : GST_MIXER_TRACK_MASTER));
+ mixer->tracklist = g_list_append (mixer->tracklist, track);
+ }
+ }
+}
+
+/* unused with G_DISABLE_* */
+static G_GNUC_UNUSED gboolean
+gst_ossmixer_contains_track (GstOssMixer * mixer, GstOssMixerTrack * osstrack)
+{
+ const GList *item;
+
+ for (item = mixer->tracklist; item != NULL; item = item->next)
+ if (item->data == osstrack)
+ return TRUE;
+
+ return FALSE;
+}
+
+const GList *
+gst_ossmixer_list_tracks (GstOssMixer * mixer)
+{
+ gst_ossmixer_ensure_track_list (mixer);
+
+ return (const GList *) mixer->tracklist;
+}
+
+void
+gst_ossmixer_get_volume (GstOssMixer * mixer,
+ GstMixerTrack * track, gint * volumes)
+{
+ gint volume;
+ GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
+
+ g_return_if_fail (mixer->fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
+
+ if (track->flags & GST_MIXER_TRACK_MUTE) {
+ volumes[0] = osstrack->lvol;
+ if (track->num_channels == 2) {
+ volumes[1] = osstrack->rvol;
+ }
+ } else {
+ /* get */
+ if (ioctl (mixer->fd, MIXER_READ (osstrack->track_num), &volume) < 0) {
+ g_warning ("Error getting recording device (%d) volume: %s",
+ osstrack->track_num, g_strerror (errno));
+ volume = 0;
+ }
+
+ osstrack->lvol = volumes[0] = (volume & 0xff);
+ if (track->num_channels == 2) {
+ osstrack->rvol = volumes[1] = ((volume >> 8) & 0xff);
+ }
+ }
+}
+
+void
+gst_ossmixer_set_mute (GstOssMixer * mixer, GstMixerTrack * track,
+ gboolean mute)
+{
+ int volume;
+ GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
+
+ g_return_if_fail (mixer->fd != -1);
+ g_return_if_fail (gst_ossmixer_contains_track (mixer, osstrack));
+
+ if (mute) {
+ volume = 0;
+ } else {
+ volume = (osstrack->lvol & 0xff);
+ if (MASK_BIT_IS_SET (mixer->stereomask, osstrack->track_num)) {
+ volume |= ((osstrack->rvol & 0xff) << 8);
+ }
+ }
+
+ if (ioctl (mixer->fd, MIXER_WRITE (osstrack->track_num), &volume) < 0) {
+ g_warning ("Error setting mixer recording device volume (0x%x): %s",
+ volume, g_strerror (errno));
+ return;
+ }
+
+ if (mute) {
+ track->flags |= GST_MIXER_TRACK_MUTE;
+ } else {
+ track->flags &= ~GST_MIXER_TRACK_MUTE;
+ }
+}
+#endif
+
+static gint
+gst_oss4_source_mixer_get_current_input (GstOss4Source * oss)
+{
+ int cur = -1;
+
+ if (ioctl (oss->fd, SNDCTL_DSP_GET_RECSRC, &cur) == -1 || cur < 0)
+ return -1;
+
+ return cur;
+}
+
+static const gchar *
+gst_oss4_source_mixer_update_record_flags (GstOss4Source * oss, gint cur_route)
+{
+ const gchar *cur_name = "";
+ GList *t;
+
+ for (t = oss->tracks; t != NULL; t = t->next) {
+ GstMixerTrack *track = t->data;
+
+ if (GST_OSS4_SOURCE_INPUT (track)->route == cur_route) {
+ if (!GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)) {
+ track->flags |= GST_MIXER_TRACK_RECORD;
+ /* no point in sending a mixer-record-changes message here */
+ }
+ cur_name = track->label;
+ } else {
+ if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)) {
+ track->flags &= ~GST_MIXER_TRACK_RECORD;
+ /* no point in sending a mixer-record-changes message here */
+ }
+ }
+ }
+
+ return cur_name;
+}
+
+static const GList *
+gst_oss4_source_mixer_list_tracks (GstMixer * mixer)
+{
+ oss_mixer_enuminfo names = { 0, };
+ GstOss4Source *oss;
+ const gchar *cur_name;
+ GList *tracks = NULL;
+ gint i, cur;
+
+ g_return_val_if_fail (mixer != NULL, NULL);
+ g_return_val_if_fail (GST_IS_OSS4_SOURCE (mixer), NULL);
+ g_return_val_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer), NULL);
+
+ oss = GST_OSS4_SOURCE (mixer);
+
+ if (oss->tracks != NULL && oss->tracks_static)
+ goto done;
+
+ if (ioctl (oss->fd, SNDCTL_DSP_GET_RECSRC_NAMES, &names) == -1)
+ goto get_recsrc_names_error;
+
+ oss->tracks_static = (names.version == 0);
+
+ GST_INFO_OBJECT (oss, "%d inputs (list is static: %s):", names.nvalues,
+ (oss->tracks_static) ? "yes" : "no");
+
+ for (i = 0; i < MIN (names.nvalues, OSS_ENUM_MAXVALUE + 1); ++i) {
+ GstMixerTrack *track;
+
+ track = g_object_new (GST_TYPE_OSS4_SOURCE_INPUT, NULL);
+ track->label = g_strdup (&names.strings[names.strindex[i]]);
+ track->flags = GST_MIXER_TRACK_INPUT;
+ track->num_channels = 2;
+ track->min_volume = 0;
+ track->max_volume = 100;
+ GST_OSS4_SOURCE_INPUT (track)->route = i;
+
+ GST_INFO_OBJECT (oss, " [%d] %s", i, track->label);
+ tracks = g_list_append (tracks, track);
+ }
+
+ gst_oss4_source_free_mixer_tracks (oss);
+ oss->tracks = tracks;
+
+done:
+
+ /* update RECORD flags */
+ cur = gst_oss4_source_mixer_get_current_input (oss);
+ cur_name = gst_oss4_source_mixer_update_record_flags (oss, cur);
+ GST_DEBUG_OBJECT (oss, "current input route: %d (%s)", cur, cur_name);
+
+ return (const GList *) oss->tracks;
+
+/* ERRORS */
+get_recsrc_names_error:
+ {
+ GST_WARNING_OBJECT (oss, "GET_RECSRC_NAMES failed: %s", g_strerror (errno));
+ return NULL;
+ }
+}
+
+static void
+gst_oss4_source_mixer_set_volume (GstMixer * mixer, GstMixerTrack * track,
+ gint * volumes)
+{
+ GstOss4Source *oss;
+ int new_vol, cur;
+
+ g_return_if_fail (mixer != NULL);
+ g_return_if_fail (track != NULL);
+ g_return_if_fail (GST_IS_MIXER_TRACK (track));
+ g_return_if_fail (GST_IS_OSS4_SOURCE (mixer));
+ g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer));
+
+ oss = GST_OSS4_SOURCE (mixer);
+
+ cur = gst_oss4_source_mixer_get_current_input (oss);
+ if (cur != GST_OSS4_SOURCE_INPUT (track)->route) {
+ GST_DEBUG_OBJECT (oss, "track not selected input route, ignoring request");
+ return;
+ }
+
+ new_vol = (volumes[1] << 8) | volumes[0];
+ if (ioctl (oss->fd, SNDCTL_DSP_SETRECVOL, &new_vol) == -1) {
+ GST_WARNING_OBJECT (oss, "SETRECVOL failed: %s", g_strerror (errno));
+ }
+}
+
+static void
+gst_oss4_source_mixer_get_volume (GstMixer * mixer, GstMixerTrack * track,
+ gint * volumes)
+{
+ GstOss4Source *oss;
+ int cur;
+
+ g_return_if_fail (mixer != NULL);
+ g_return_if_fail (GST_IS_OSS4_SOURCE (mixer));
+ g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer));
+
+ oss = GST_OSS4_SOURCE (mixer);
+
+ cur = gst_oss4_source_mixer_get_current_input (oss);
+ if (cur != GST_OSS4_SOURCE_INPUT (track)->route) {
+ volumes[0] = 0;
+ volumes[1] = 0;
+ } else {
+ int vol = -1;
+
+ if (ioctl (oss->fd, SNDCTL_DSP_GETRECVOL, &vol) == -1 || vol < 0) {
+ GST_WARNING_OBJECT (oss, "GETRECVOL failed: %s", g_strerror (errno));
+ volumes[0] = 100;
+ volumes[1] = 100;
+ } else {
+ volumes[0] = MIN (100, vol & 0xff);
+ volumes[1] = MIN (100, (vol >> 8) & 0xff);
+ }
+ }
+}
+
+static void
+gst_oss4_source_mixer_set_record (GstMixer * mixer, GstMixerTrack * track,
+ gboolean record)
+{
+ GstOss4Source *oss;
+ const gchar *cur_name;
+ gint cur;
+
+ g_return_if_fail (mixer != NULL);
+ g_return_if_fail (track != NULL);
+ g_return_if_fail (GST_IS_MIXER_TRACK (track));
+ g_return_if_fail (GST_IS_OSS4_SOURCE (mixer));
+ g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer));
+
+ oss = GST_OSS4_SOURCE (mixer);
+
+ cur = gst_oss4_source_mixer_get_current_input (oss);
+
+ /* stop recording for an input that's not selected anyway => nothing to do */
+ if (!record && cur != GST_OSS4_SOURCE_INPUT (track)->route)
+ goto done;
+
+ /* select recording for an input that's already selected => nothing to do
+ * (or should we mess with the recording volume in this case maybe?) */
+ if (record && cur == GST_OSS4_SOURCE_INPUT (track)->route)
+ goto done;
+
+ /* make current input stop recording: we can't really make an input stop
+ * recording, we can only select an input FOR recording, so we'll just ignore
+ * all requests to stop for now */
+ if (!record) {
+ GST_WARNING_OBJECT (oss, "Can't un-select an input as such, only switch "
+ "to a different input source");
+ /* FIXME: set recording volume to 0 maybe? */
+ } else {
+ int new_route = GST_OSS4_SOURCE_INPUT (track)->route;
+
+ /* select this input for recording */
+
+ if (ioctl (oss->fd, SNDCTL_DSP_SET_RECSRC, &new_route) == -1) {
+ GST_WARNING_OBJECT (oss, "Could not select input %d for recording: %s",
+ new_route, g_strerror (errno));
+ } else {
+ cur = new_route;
+ }
+ }
+
+done:
+
+ cur_name = gst_oss4_source_mixer_update_record_flags (oss, cur);
+ GST_DEBUG_OBJECT (oss, "active input route: %d (%s)", cur, cur_name);
+}
+
+static void
+gst_oss4_source_mixer_set_mute (GstMixer * mixer, GstMixerTrack * track,
+ gboolean mute)
+{
+ g_return_if_fail (mixer != NULL);
+ g_return_if_fail (track != NULL);
+ g_return_if_fail (GST_IS_MIXER_TRACK (track));
+ g_return_if_fail (GST_IS_OSS4_SOURCE (mixer));
+ g_return_if_fail (GST_OSS4_SOURCE_IS_OPEN (mixer));
+
+ /* FIXME: implement gst_oss4_source_mixer_set_mute() - what to do here? */
+ /* oss4_mixer_set_mute (mixer->mixer, track, mute); */
+}
+
+static void
+gst_oss4_source_mixer_interface_init (GstMixerClass * klass)
+{
+ GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE;
+
+ klass->list_tracks = gst_oss4_source_mixer_list_tracks;
+ klass->set_volume = gst_oss4_source_mixer_set_volume;
+ klass->get_volume = gst_oss4_source_mixer_get_volume;
+ klass->set_mute = gst_oss4_source_mixer_set_mute;
+ klass->set_record = gst_oss4_source_mixer_set_record;
+}
+
+/* Implement the horror that is GstImplementsInterface */
+
+static gboolean
+gst_oss4_source_mixer_supported (GstImplementsInterface * iface,
+ GType iface_type)
+{
+ GstOss4Source *oss;
+ gboolean is_open;
+
+ g_return_val_if_fail (GST_IS_OSS4_SOURCE (iface), FALSE);
+ g_return_val_if_fail (iface_type == GST_TYPE_MIXER, FALSE);
+
+ oss = GST_OSS4_SOURCE (iface);
+
+ GST_OBJECT_LOCK (oss);
+ is_open = GST_OSS4_SOURCE_IS_OPEN (iface);
+ GST_OBJECT_UNLOCK (oss);
+
+ return is_open;
+}
+
+static void
+gst_oss4_source_mixer_implements_interface_init (GstImplementsInterfaceClass *
+ klass)
+{
+ klass->supported = gst_oss4_source_mixer_supported;
+}
+
+static void
+gst_oss4_source_init_interfaces (GType type)
+{
+ static const GInterfaceInfo implements_iface_info = {
+ (GInterfaceInitFunc) gst_oss4_source_mixer_implements_interface_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo mixer_iface_info = {
+ (GInterfaceInitFunc) gst_oss4_source_mixer_interface_init,
+ NULL,
+ NULL,
+ };
+
+ g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
+ &implements_iface_info);
+ g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
+
+ gst_oss4_add_property_probe_interface (type);
+}
diff --git a/sys/oss4/oss4-source.h b/sys/oss4/oss4-source.h
new file mode 100644
index 0000000..3a86b43
--- /dev/null
+++ b/sys/oss4/oss4-source.h
@@ -0,0 +1,89 @@
+/* GStreamer OSS4 audio source
+ * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular 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.
+ */
+
+#ifndef GST_OSS4_SOURCE_H
+#define GST_OSS4_SOURCE_H
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosrc.h>
+#include <gst/interfaces/mixertrack.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSS4_SOURCE (gst_oss4_source_get_type())
+#define GST_OSS4_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_SOURCE,GstOss4Source))
+#define GST_OSS4_SOURCE_CAST(obj) ((GstOss4Source *)(obj))
+#define GST_OSS4_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_SOURCE,GstOss4SourceClass))
+#define GST_IS_OSS4_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_SOURCE))
+#define GST_IS_OSS4_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_SOURCE))
+
+typedef struct _GstOss4Source GstOss4Source;
+typedef struct _GstOss4SourceClass GstOss4SourceClass;
+
+struct _GstOss4Source {
+ GstAudioSrc audiosrc;
+
+ gchar * device; /* NULL if none was set */
+ gchar * open_device; /* the device we opened */
+ gchar * device_name; /* set if the device is open */
+ gint fd; /* -1 if not open */
+ gint bytes_per_sample;
+
+ GstCaps * probed_caps;
+
+ /* property probe interface */
+ GList * property_probe_list;
+
+ /* mixer interface */
+ GList * tracks;
+ gboolean tracks_static; /* FALSE if the list of inputs may change */
+};
+
+struct _GstOss4SourceClass {
+ GstAudioSrcClass audiosrc_class;
+};
+
+GType gst_oss4_source_get_type (void);
+
+/* our mixer track for input selection */
+#define GST_TYPE_OSS4_SOURCE_INPUT (gst_oss4_source_input_get_type())
+#define GST_OSS4_SOURCE_INPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS4_SOURCE_INPUT,GstOss4SourceInput))
+#define GST_OSS4_SOURCE_INPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS4_SOURCE_INPUT,GstOss4SourceInputClass))
+#define GST_IS_OSS4_SOURCE_INPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS4_SOURCE_INPUT))
+#define GST_IS_OSS4_SOURCE_INPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS4_SOURCE_INPUT))
+
+typedef struct _GstOss4SourceInput GstOss4SourceInput;
+typedef struct _GstOss4SourceInputClass GstOss4SourceInputClass;
+
+struct _GstOss4SourceInput {
+ GstMixerTrack mixer_track;
+
+ int route; /* number for SNDCTL_DSP_SET_RECSRC etc. */
+};
+
+struct _GstOss4SourceInputClass {
+ GstMixerTrackClass mixer_track_class;
+};
+
+GType gst_oss4_source_input_get_type (void);
+
+G_END_DECLS
+
+#endif /* GST_OSS4_SOURCE_H */
+
diff --git a/sys/osxaudio/Makefile.am b/sys/osxaudio/Makefile.am
new file mode 100644
index 0000000..cfd0c4d
--- /dev/null
+++ b/sys/osxaudio/Makefile.am
@@ -0,0 +1,26 @@
+plugin_LTLIBRARIES = libgstosxaudio.la
+
+libgstosxaudio_la_SOURCES = gstosxringbuffer.c \
+ gstosxaudioelement.c \
+ gstosxaudiosink.c \
+ gstosxaudiosrc.c \
+ gstosxaudio.c
+
+libgstosxaudio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \
+ -Wno-deprecated-declarations
+libgstosxaudio_la_LIBADD = \
+ -lgstinterfaces-@GST_MAJORMINOR@ \
+ -lgstaudio-@GST_MAJORMINOR@ \
+ $(GST_PLUGINS_BASE_LIBS) \
+ $(GST_BASE_LIBS) \
+ $(GST_LIBS)
+libgstosxaudio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -Wl,-framework -Wl,CoreAudio -Wl,-framework -Wl,AudioUnit -Wl,-framework -Wl,CoreServices
+libgstosxaudio_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = gstosxaudiosink.h \
+ gstosxaudioelement.h \
+ gstosxringbuffer.h \
+ gstosxaudiosrc.h
+
+
+
diff --git a/sys/osxaudio/Makefile.in b/sys/osxaudio/Makefile.in
new file mode 100644
index 0000000..9e8e186
--- /dev/null
+++ b/sys/osxaudio/Makefile.in
@@ -0,0 +1,858 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sys/osxaudio
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
+ $(top_srcdir)/common/m4/as-auto-alt.m4 \
+ $(top_srcdir)/common/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/common/m4/as-gcc-inline-assembly.m4 \
+ $(top_srcdir)/common/m4/as-objc.m4 \
+ $(top_srcdir)/common/m4/as-python.m4 \
+ $(top_srcdir)/common/m4/as-scrub-include.m4 \
+ $(top_srcdir)/common/m4/as-version.m4 \
+ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
+ $(top_srcdir)/common/m4/gst-arch.m4 \
+ $(top_srcdir)/common/m4/gst-args.m4 \
+ $(top_srcdir)/common/m4/gst-check.m4 \
+ $(top_srcdir)/common/m4/gst-default.m4 \
+ $(top_srcdir)/common/m4/gst-dowhile.m4 \
+ $(top_srcdir)/common/m4/gst-error.m4 \
+ $(top_srcdir)/common/m4/gst-feature.m4 \
+ $(top_srcdir)/common/m4/gst-gettext.m4 \
+ $(top_srcdir)/common/m4/gst-glib2.m4 \
+ $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \
+ $(top_srcdir)/common/m4/gst-platform.m4 \
+ $(top_srcdir)/common/m4/gst-plugin-docs.m4 \
+ $(top_srcdir)/common/m4/gst-plugindir.m4 \
+ $(top_srcdir)/common/m4/gst-x11.m4 \
+ $(top_srcdir)/common/m4/gst.m4 \
+ $(top_srcdir)/common/m4/gtk-doc.m4 \
+ $(top_srcdir)/common/m4/orc.m4 $(top_srcdir)/common/m4/pkg.m4 \
+ $(top_srcdir)/m4/aalib.m4 $(top_srcdir)/m4/esd.m4 \
+ $(top_srcdir)/m4/gconf-2.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gst-fionread.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgstosxaudio_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libgstosxaudio_la_OBJECTS = libgstosxaudio_la-gstosxringbuffer.lo \
+ libgstosxaudio_la-gstosxaudioelement.lo \
+ libgstosxaudio_la-gstosxaudiosink.lo \
+ libgstosxaudio_la-gstosxaudiosrc.lo \
+ libgstosxaudio_la-gstosxaudio.lo
+libgstosxaudio_la_OBJECTS = $(am_libgstosxaudio_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libgstosxaudio_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(libgstosxaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
+ $(CCLD) $(libgstosxaudio_la_CFLAGS) $(CFLAGS) \
+ $(libgstosxaudio_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libgstosxaudio_la_SOURCES)
+DIST_SOURCES = $(libgstosxaudio_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+AALIB_CFLAGS = @AALIB_CFLAGS@
+AALIB_CONFIG = @AALIB_CONFIG@
+AALIB_LIBS = @AALIB_LIBS@
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+ANNODEX_CFLAGS = @ANNODEX_CFLAGS@
+ANNODEX_LIBS = @ANNODEX_LIBS@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BZ2_LIBS = @BZ2_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_GOBJECT_CFLAGS = @CAIRO_GOBJECT_CFLAGS@
+CAIRO_GOBJECT_LIBS = @CAIRO_GOBJECT_LIBS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@
+DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@
+DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@
+DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@
+DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@
+DIRECTSOUND_CFLAGS = @DIRECTSOUND_CFLAGS@
+DIRECTSOUND_LDFLAGS = @DIRECTSOUND_LDFLAGS@
+DIRECTSOUND_LIBS = @DIRECTSOUND_LIBS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DV1394_CFLAGS = @DV1394_CFLAGS@
+DV1394_LIBS = @DV1394_LIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ERROR_CFLAGS = @ERROR_CFLAGS@
+ERROR_CXXFLAGS = @ERROR_CXXFLAGS@
+ESD_CFLAGS = @ESD_CFLAGS@
+ESD_CONFIG = @ESD_CONFIG@
+ESD_LIBS = @ESD_LIBS@
+EXEEXT = @EXEEXT@
+FFLAGS = @FFLAGS@
+FGREP = @FGREP@
+FLAC_CFLAGS = @FLAC_CFLAGS@
+FLAC_LIBS = @FLAC_LIBS@
+GCONFTOOL = @GCONFTOOL@
+GCONF_CFLAGS = @GCONF_CFLAGS@
+GCONF_LIBS = @GCONF_LIBS@
+GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+GCOV = @GCOV@
+GCOV_CFLAGS = @GCOV_CFLAGS@
+GCOV_LIBS = @GCOV_LIBS@
+GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@
+GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_PREFIX = @GLIB_PREFIX@
+GLIB_REQ = @GLIB_REQ@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@
+GSTPB_PREFIX = @GSTPB_PREFIX@
+GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@
+GST_BASE_CFLAGS = @GST_BASE_CFLAGS@
+GST_BASE_LIBS = @GST_BASE_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_CONTROLLER_CFLAGS = @GST_CONTROLLER_CFLAGS@
+GST_CONTROLLER_LIBS = @GST_CONTROLLER_LIBS@
+GST_CXXFLAGS = @GST_CXXFLAGS@
+GST_GDP_CFLAGS = @GST_GDP_CFLAGS@
+GST_GDP_LIBS = @GST_GDP_LIBS@
+GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@
+GST_LIBS = @GST_LIBS@
+GST_LICENSE = @GST_LICENSE@
+GST_LT_LDFLAGS = @GST_LT_LDFLAGS@
+GST_MAJORMINOR = @GST_MAJORMINOR@
+GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@
+GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@
+GST_PACKAGE_NAME = @GST_PACKAGE_NAME@
+GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@
+GST_PLUGINS_ALL = @GST_PLUGINS_ALL@
+GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@
+GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@
+GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@
+GST_PLUGINS_DIR = @GST_PLUGINS_DIR@
+GST_PLUGINS_SELECTED = @GST_PLUGINS_SELECTED@
+GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@
+GST_PREFIX = @GST_PREFIX@
+GST_TOOLS_DIR = @GST_TOOLS_DIR@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_X11_CFLAGS = @GTK_X11_CFLAGS@
+GTK_X11_LIBS = @GTK_X11_LIBS@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+HAVE_AVC1394 = @HAVE_AVC1394@
+HAVE_BZ2 = @HAVE_BZ2@
+HAVE_CXX = @HAVE_CXX@
+HAVE_DIRECTSOUND = @HAVE_DIRECTSOUND@
+HAVE_GCONFTOOL = @HAVE_GCONFTOOL@
+HAVE_ROM1394 = @HAVE_ROM1394@
+HAVE_SPEEX = @HAVE_SPEEX@
+HAVE_X = @HAVE_X@
+HAVE_XSHM = @HAVE_XSHM@
+HAVE_ZLIB = @HAVE_ZLIB@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JACK_0_120_1_CFLAGS = @JACK_0_120_1_CFLAGS@
+JACK_0_120_1_LIBS = @JACK_0_120_1_LIBS@
+JACK_1_9_7_CFLAGS = @JACK_1_9_7_CFLAGS@
+JACK_1_9_7_LIBS = @JACK_1_9_7_LIBS@
+JACK_CFLAGS = @JACK_CFLAGS@
+JACK_LIBS = @JACK_LIBS@
+JPEG_LIBS = @JPEG_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCACA_CFLAGS = @LIBCACA_CFLAGS@
+LIBCACA_LIBS = @LIBCACA_LIBS@
+LIBDV_CFLAGS = @LIBDV_CFLAGS@
+LIBDV_LIBS = @LIBDV_LIBS@
+LIBICONV = @LIBICONV@
+LIBIEC61883_CFLAGS = @LIBIEC61883_CFLAGS@
+LIBIEC61883_LIBS = @LIBIEC61883_LIBS@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBPNG_CFLAGS = @LIBPNG_CFLAGS@
+LIBPNG_LIBS = @LIBPNG_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBV4L2_CFLAGS = @LIBV4L2_CFLAGS@
+LIBV4L2_LIBS = @LIBV4L2_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCALEDIR = @LOCALEDIR@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJC_LDFLAGS = @OBJC_LDFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORCC = @ORCC@
+ORCC_FLAGS = @ORCC_FLAGS@
+ORC_CFLAGS = @ORC_CFLAGS@
+ORC_LIBS = @ORC_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@
+PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PLUGINDIR = @PLUGINDIR@
+POSUB = @POSUB@
+PROFILE_CFLAGS = @PROFILE_CFLAGS@
+PULSE_0_9_20_CFLAGS = @PULSE_0_9_20_CFLAGS@
+PULSE_0_9_20_LIBS = @PULSE_0_9_20_LIBS@
+PULSE_1_0_CFLAGS = @PULSE_1_0_CFLAGS@
+PULSE_1_0_LIBS = @PULSE_1_0_LIBS@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RAW1394_CFLAGS = @RAW1394_CFLAGS@
+RAW1394_LIBS = @RAW1394_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHOUT2_CFLAGS = @SHOUT2_CFLAGS@
+SHOUT2_LIBS = @SHOUT2_LIBS@
+SOUP_CFLAGS = @SOUP_CFLAGS@
+SOUP_LIBS = @SOUP_LIBS@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+TAGLIB_CFLAGS = @TAGLIB_CFLAGS@
+TAGLIB_CXXFLAGS = @TAGLIB_CXXFLAGS@
+TAGLIB_LIBS = @TAGLIB_LIBS@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VALGRIND_PATH = @VALGRIND_PATH@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
+WAVPACK_LIBS = @WAVPACK_LIBS@
+WIN32_LIBS = @WIN32_LIBS@
+XDAMAGE_CFLAGS = @XDAMAGE_CFLAGS@
+XDAMAGE_LIBS = @XDAMAGE_LIBS@
+XFIXES_CFLAGS = @XFIXES_CFLAGS@
+XFIXES_LIBS = @XFIXES_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+XMKMF = @XMKMF@
+XSHM_LIBS = @XSHM_LIBS@
+XVIDEO_LIBS = @XVIDEO_LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = libgstosxaudio.la
+libgstosxaudio_la_SOURCES = gstosxringbuffer.c \
+ gstosxaudioelement.c \
+ gstosxaudiosink.c \
+ gstosxaudiosrc.c \
+ gstosxaudio.c
+
+libgstosxaudio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \
+ -Wno-deprecated-declarations
+
+libgstosxaudio_la_LIBADD = \
+ -lgstinterfaces-@GST_MAJORMINOR@ \
+ -lgstaudio-@GST_MAJORMINOR@ \
+ $(GST_PLUGINS_BASE_LIBS) \
+ $(GST_BASE_LIBS) \
+ $(GST_LIBS)
+
+libgstosxaudio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -Wl,-framework -Wl,CoreAudio -Wl,-framework -Wl,AudioUnit -Wl,-framework -Wl,CoreServices
+libgstosxaudio_la_LIBTOOLFLAGS = --tag=disable-static
+noinst_HEADERS = gstosxaudiosink.h \
+ gstosxaudioelement.h \
+ gstosxringbuffer.h \
+ gstosxaudiosrc.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sys/osxaudio/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu sys/osxaudio/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgstosxaudio.la: $(libgstosxaudio_la_OBJECTS) $(libgstosxaudio_la_DEPENDENCIES) $(EXTRA_libgstosxaudio_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgstosxaudio_la_LINK) -rpath $(plugindir) $(libgstosxaudio_la_OBJECTS) $(libgstosxaudio_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstosxaudio_la-gstosxaudio.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstosxaudio_la-gstosxaudioelement.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstosxaudio_la-gstosxaudiosink.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstosxaudio_la-gstosxaudiosrc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstosxaudio_la-gstosxringbuffer.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libgstosxaudio_la-gstosxringbuffer.lo: gstosxringbuffer.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstosxaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstosxaudio_la_CFLAGS) $(CFLAGS) -MT libgstosxaudio_la-gstosxringbuffer.lo -MD -MP -MF $(DEPDIR)/libgstosxaudio_la-gstosxringbuffer.Tpo -c -o libgstosxaudio_la-gstosxringbuffer.lo `test -f 'gstosxringbuffer.c' || echo '$(srcdir)/'`gstosxringbuffer.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstosxaudio_la-gstosxringbuffer.Tpo $(DEPDIR)/libgstosxaudio_la-gstosxringbuffer.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstosxringbuffer.c' object='libgstosxaudio_la-gstosxringbuffer.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstosxaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstosxaudio_la_CFLAGS) $(CFLAGS) -c -o libgstosxaudio_la-gstosxringbuffer.lo `test -f 'gstosxringbuffer.c' || echo '$(srcdir)/'`gstosxringbuffer.c
+
+libgstosxaudio_la-gstosxaudioelement.lo: gstosxaudioelement.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstosxaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstosxaudio_la_CFLAGS) $(CFLAGS) -MT libgstosxaudio_la-gstosxaudioelement.lo -MD -MP -MF $(DEPDIR)/libgstosxaudio_la-gstosxaudioelement.Tpo -c -o libgstosxaudio_la-gstosxaudioelement.lo `test -f 'gstosxaudioelement.c' || echo '$(srcdir)/'`gstosxaudioelement.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstosxaudio_la-gstosxaudioelement.Tpo $(DEPDIR)/libgstosxaudio_la-gstosxaudioelement.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstosxaudioelement.c' object='libgstosxaudio_la-gstosxaudioelement.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstosxaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstosxaudio_la_CFLAGS) $(CFLAGS) -c -o libgstosxaudio_la-gstosxaudioelement.lo `test -f 'gstosxaudioelement.c' || echo '$(srcdir)/'`gstosxaudioelement.c
+
+libgstosxaudio_la-gstosxaudiosink.lo: gstosxaudiosink.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstosxaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstosxaudio_la_CFLAGS) $(CFLAGS) -MT libgstosxaudio_la-gstosxaudiosink.lo -MD -MP -MF $(DEPDIR)/libgstosxaudio_la-gstosxaudiosink.Tpo -c -o libgstosxaudio_la-gstosxaudiosink.lo `test -f 'gstosxaudiosink.c' || echo '$(srcdir)/'`gstosxaudiosink.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstosxaudio_la-gstosxaudiosink.Tpo $(DEPDIR)/libgstosxaudio_la-gstosxaudiosink.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstosxaudiosink.c' object='libgstosxaudio_la-gstosxaudiosink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstosxaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstosxaudio_la_CFLAGS) $(CFLAGS) -c -o libgstosxaudio_la-gstosxaudiosink.lo `test -f 'gstosxaudiosink.c' || echo '$(srcdir)/'`gstosxaudiosink.c
+
+libgstosxaudio_la-gstosxaudiosrc.lo: gstosxaudiosrc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstosxaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstosxaudio_la_CFLAGS) $(CFLAGS) -MT libgstosxaudio_la-gstosxaudiosrc.lo -MD -MP -MF $(DEPDIR)/libgstosxaudio_la-gstosxaudiosrc.Tpo -c -o libgstosxaudio_la-gstosxaudiosrc.lo `test -f 'gstosxaudiosrc.c' || echo '$(srcdir)/'`gstosxaudiosrc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstosxaudio_la-gstosxaudiosrc.Tpo $(DEPDIR)/libgstosxaudio_la-gstosxaudiosrc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstosxaudiosrc.c' object='libgstosxaudio_la-gstosxaudiosrc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstosxaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstosxaudio_la_CFLAGS) $(CFLAGS) -c -o libgstosxaudio_la-gstosxaudiosrc.lo `test -f 'gstosxaudiosrc.c' || echo '$(srcdir)/'`gstosxaudiosrc.c
+
+libgstosxaudio_la-gstosxaudio.lo: gstosxaudio.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstosxaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstosxaudio_la_CFLAGS) $(CFLAGS) -MT libgstosxaudio_la-gstosxaudio.lo -MD -MP -MF $(DEPDIR)/libgstosxaudio_la-gstosxaudio.Tpo -c -o libgstosxaudio_la-gstosxaudio.lo `test -f 'gstosxaudio.c' || echo '$(srcdir)/'`gstosxaudio.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstosxaudio_la-gstosxaudio.Tpo $(DEPDIR)/libgstosxaudio_la-gstosxaudio.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstosxaudio.c' object='libgstosxaudio_la-gstosxaudio.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstosxaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstosxaudio_la_CFLAGS) $(CFLAGS) -c -o libgstosxaudio_la-gstosxaudio.lo `test -f 'gstosxaudio.c' || echo '$(srcdir)/'`gstosxaudio.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sys/osxaudio/gstosxaudio.c b/sys/osxaudio/gstosxaudio.c
new file mode 100644
index 0000000..1ddfce4
--- /dev/null
+++ b/sys/osxaudio/gstosxaudio.c
@@ -0,0 +1,53 @@
+/*
+ * GStreamer
+ * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) 2007,2008 Pioneers of the Inevitable <songbird@songbirdnest.com>
+ *
+ * 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.
+ *
+ * The development of this code was made possible due to the involvement of
+ * Pioneers of the Inevitable, the creators of the Songbird Music player
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstosxaudioelement.h"
+#include "gstosxaudiosink.h"
+#include "gstosxaudiosrc.h"
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ if (!gst_element_register (plugin, "osxaudiosink", GST_RANK_PRIMARY,
+ GST_TYPE_OSX_AUDIO_SINK)) {
+ return FALSE;
+ }
+ if (!gst_element_register (plugin, "osxaudiosrc", GST_RANK_PRIMARY,
+ GST_TYPE_OSX_AUDIO_SRC)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "osxaudio",
+ "OSX (Mac OS X) audio support for GStreamer",
+ plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/osxaudio/gstosxaudioelement.c b/sys/osxaudio/gstosxaudioelement.c
new file mode 100644
index 0000000..a41f4b8
--- /dev/null
+++ b/sys/osxaudio/gstosxaudioelement.c
@@ -0,0 +1,92 @@
+/*
+ * GStreamer
+ * Copyright (C) 2006 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+ * Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.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.
+ *
+ * The development of this code was made possible due to the involvement of
+ * Pioneers of the Inevitable, the creators of the Songbird Music player
+ *
+ */
+
+#include <gst/gst.h>
+#include "gstosxaudioelement.h"
+
+static void
+gst_osx_audio_element_class_init (GstOsxAudioElementInterface * klass);
+
+GType
+gst_osx_audio_element_get_type (void)
+{
+ static GType gst_osxaudioelement_type = 0;
+
+ if (!gst_osxaudioelement_type) {
+ static const GTypeInfo gst_osxaudioelement_info = {
+ sizeof (GstOsxAudioElementInterface),
+ (GBaseInitFunc) gst_osx_audio_element_class_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL,
+ NULL
+ };
+
+ gst_osxaudioelement_type = g_type_register_static (G_TYPE_INTERFACE,
+ "GstOsxAudioElement", &gst_osxaudioelement_info, 0);
+ }
+
+ return gst_osxaudioelement_type;
+}
+
+static void
+gst_osx_audio_element_class_init (GstOsxAudioElementInterface * klass)
+{
+ static gboolean initialized = FALSE;
+
+ if (!initialized) {
+ initialized = TRUE;
+ }
+
+ /* default virtual functions */
+ klass->io_proc = NULL;
+}
diff --git a/sys/osxaudio/gstosxaudioelement.h b/sys/osxaudio/gstosxaudioelement.h
new file mode 100644
index 0000000..b5d90c0
--- /dev/null
+++ b/sys/osxaudio/gstosxaudioelement.h
@@ -0,0 +1,84 @@
+/*
+ * GStreamer
+ * Copyright (C) 2006 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+ * Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.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.
+ *
+ * The development of this code was made possible due to the involvement of
+ * Pioneers of the Inevitable, the creators of the Songbird Music player
+ *
+ */
+
+#ifndef __GST_OSX_AUDIO_ELEMENT_H__
+#define __GST_OSX_AUDIO_ELEMENT_H__
+
+#include <gst/gst.h>
+#include <CoreAudio/CoreAudio.h>
+#include <AudioUnit/AudioUnit.h>
+
+G_BEGIN_DECLS
+
+#define GST_OSX_AUDIO_ELEMENT_TYPE \
+ (gst_osx_audio_element_get_type())
+#define GST_OSX_AUDIO_ELEMENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_OSX_AUDIO_ELEMENT_TYPE,GstOsxAudioElementInterface))
+#define GST_IS_OSX_AUDIO_ELEMENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_OSX_AUDIO_ELEMENT_TYPE))
+#define GST_OSX_AUDIO_ELEMENT_GET_INTERFACE(inst) \
+ (G_TYPE_INSTANCE_GET_INTERFACE((inst),GST_OSX_AUDIO_ELEMENT_TYPE,GstOsxAudioElementInterface))
+
+typedef struct _GstOsxAudioElementInterface GstOsxAudioElementInterface;
+
+struct _GstOsxAudioElementInterface
+{
+ GTypeInterface parent;
+
+ OSStatus (*io_proc) (void * userdata,
+ AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber, UInt32 inNumberFrames,
+ AudioBufferList * bufferList);
+};
+
+GType gst_osx_audio_element_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OSX_AUDIO_ELEMENT_H__ */
diff --git a/sys/osxaudio/gstosxaudiosink.c b/sys/osxaudio/gstosxaudiosink.c
new file mode 100644
index 0000000..cd456e5
--- /dev/null
+++ b/sys/osxaudio/gstosxaudiosink.c
@@ -0,0 +1,348 @@
+/*
+ * GStreamer
+ * Copyright (C) 2005,2006 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+ * Copyright (C) 2007,2008 Pioneers of the Inevitable <songbird@songbirdnest.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.
+ *
+ * The development of this code was made possible due to the involvement of
+ * Pioneers of the Inevitable, the creators of the Songbird Music player
+ *
+ */
+
+/**
+ * SECTION:element-osxaudiosink
+ *
+ * This element renders raw audio samples using the CoreAudio api.
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * |[
+ * gst-launch filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! osxaudiosink
+ * ]| Play an Ogg/Vorbis file.
+ * </refsect2>
+ *
+ * Last reviewed on 2006-03-01 (0.10.4)
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gst/gst.h>
+#include <CoreAudio/CoreAudio.h>
+#include <CoreAudio/AudioHardware.h>
+#include "gstosxaudiosink.h"
+#include "gstosxaudioelement.h"
+
+GST_DEBUG_CATEGORY_STATIC (osx_audiosink_debug);
+#define GST_CAT_DEFAULT osx_audiosink_debug
+
+/* Filter signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum
+{
+ ARG_0,
+ ARG_DEVICE,
+ ARG_VOLUME
+};
+
+#define DEFAULT_VOLUME 1.0
+
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-float, "
+ "endianness = (int) {" G_STRINGIFY (G_BYTE_ORDER) " }, "
+ "signed = (boolean) { TRUE }, "
+ "width = (int) 32, "
+ "depth = (int) 32, "
+ "rate = (int) [1, MAX], " "channels = (int) [1, MAX]")
+ );
+
+static void gst_osx_audio_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_osx_audio_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static GstRingBuffer *gst_osx_audio_sink_create_ringbuffer (GstBaseAudioSink *
+ sink);
+static void gst_osx_audio_sink_osxelement_init (gpointer g_iface,
+ gpointer iface_data);
+static void gst_osx_audio_sink_select_device (GstOsxAudioSink * osxsink);
+static void gst_osx_audio_sink_set_volume (GstOsxAudioSink * sink);
+
+static OSStatus gst_osx_audio_sink_io_proc (GstOsxRingBuffer * buf,
+ AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * bufferList);
+
+static void
+gst_osx_audio_sink_do_init (GType type)
+{
+ static const GInterfaceInfo osxelement_info = {
+ gst_osx_audio_sink_osxelement_init,
+ NULL,
+ NULL
+ };
+
+ GST_DEBUG_CATEGORY_INIT (osx_audiosink_debug, "osxaudiosink", 0,
+ "OSX Audio Sink");
+ GST_DEBUG ("Adding static interface");
+ g_type_add_interface_static (type, GST_OSX_AUDIO_ELEMENT_TYPE,
+ &osxelement_info);
+}
+
+GST_BOILERPLATE_FULL (GstOsxAudioSink, gst_osx_audio_sink, GstBaseAudioSink,
+ GST_TYPE_BASE_AUDIO_SINK, gst_osx_audio_sink_do_init);
+
+static void
+gst_osx_audio_sink_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_add_static_pad_template (element_class, &sink_factory);
+
+ gst_element_class_set_details_simple (element_class, "Audio Sink (OSX)",
+ "Sink/Audio",
+ "Output to a sound card in OS X",
+ "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
+}
+
+static void
+gst_osx_audio_sink_class_init (GstOsxAudioSinkClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSinkClass *gstbasesink_class;
+ GstBaseAudioSinkClass *gstbaseaudiosink_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesink_class = (GstBaseSinkClass *) klass;
+ gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->set_property = gst_osx_audio_sink_set_property;
+ gobject_class->get_property = gst_osx_audio_sink_get_property;
+
+ g_object_class_install_property (gobject_class, ARG_DEVICE,
+ g_param_spec_int ("device", "Device ID", "Device ID of output device",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, ARG_VOLUME,
+ g_param_spec_double ("volume", "Volume", "Volume of this stream",
+ 0, 1.0, 1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ gstbaseaudiosink_class->create_ringbuffer =
+ GST_DEBUG_FUNCPTR (gst_osx_audio_sink_create_ringbuffer);
+}
+
+static void
+gst_osx_audio_sink_init (GstOsxAudioSink * sink, GstOsxAudioSinkClass * gclass)
+{
+ GST_DEBUG ("Initialising object");
+
+ sink->device_id = kAudioDeviceUnknown;
+ sink->volume = DEFAULT_VOLUME;
+}
+
+static void
+gst_osx_audio_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOsxAudioSink *sink = GST_OSX_AUDIO_SINK (object);
+
+ switch (prop_id) {
+ case ARG_DEVICE:
+ sink->device_id = g_value_get_int (value);
+ break;
+ case ARG_VOLUME:
+ sink->volume = g_value_get_double (value);
+ gst_osx_audio_sink_set_volume (sink);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_osx_audio_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstOsxAudioSink *sink = GST_OSX_AUDIO_SINK (object);
+ switch (prop_id) {
+ case ARG_DEVICE:
+ g_value_set_int (value, sink->device_id);
+ break;
+ case ARG_VOLUME:
+ g_value_set_double (value, sink->volume);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstRingBuffer *
+gst_osx_audio_sink_create_ringbuffer (GstBaseAudioSink * sink)
+{
+ GstOsxAudioSink *osxsink;
+ GstOsxRingBuffer *ringbuffer;
+
+ osxsink = GST_OSX_AUDIO_SINK (sink);
+
+ gst_osx_audio_sink_select_device (osxsink);
+
+ GST_DEBUG ("Creating ringbuffer");
+ ringbuffer = g_object_new (GST_TYPE_OSX_RING_BUFFER, NULL);
+ GST_DEBUG ("osx sink 0x%p element 0x%p ioproc 0x%p", osxsink,
+ GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink),
+ (void *) gst_osx_audio_sink_io_proc);
+
+ gst_osx_audio_sink_set_volume (osxsink);
+
+ ringbuffer->element = GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink);
+ ringbuffer->device_id = osxsink->device_id;
+
+ return GST_RING_BUFFER (ringbuffer);
+}
+
+/* HALOutput AudioUnit will request fairly arbitrarily-sized chunks of data,
+ * not of a fixed size. So, we keep track of where in the current ringbuffer
+ * segment we are, and only advance the segment once we've read the whole
+ * thing */
+static OSStatus
+gst_osx_audio_sink_io_proc (GstOsxRingBuffer * buf,
+ AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * bufferList)
+{
+ guint8 *readptr;
+ gint readseg;
+ gint len;
+ gint remaining = bufferList->mBuffers[0].mDataByteSize;
+ gint offset = 0;
+
+ while (remaining) {
+ if (!gst_ring_buffer_prepare_read (GST_RING_BUFFER (buf),
+ &readseg, &readptr, &len))
+ return 0;
+
+ len -= buf->segoffset;
+
+ if (len > remaining)
+ len = remaining;
+
+ memcpy ((char *) bufferList->mBuffers[0].mData + offset,
+ readptr + buf->segoffset, len);
+
+ buf->segoffset += len;
+ offset += len;
+ remaining -= len;
+
+ if ((gint) buf->segoffset == GST_RING_BUFFER (buf)->spec.segsize) {
+ /* clear written samples */
+ gst_ring_buffer_clear (GST_RING_BUFFER (buf), readseg);
+
+ /* we wrote one segment */
+ gst_ring_buffer_advance (GST_RING_BUFFER (buf), 1);
+
+ buf->segoffset = 0;
+ }
+ }
+ return 0;
+}
+
+static void
+gst_osx_audio_sink_osxelement_init (gpointer g_iface, gpointer iface_data)
+{
+ GstOsxAudioElementInterface *iface = (GstOsxAudioElementInterface *) g_iface;
+
+ iface->io_proc = (AURenderCallback) gst_osx_audio_sink_io_proc;
+}
+
+static void
+gst_osx_audio_sink_set_volume (GstOsxAudioSink * sink)
+{
+ if (!sink->audiounit)
+ return;
+
+ AudioUnitSetParameter (sink->audiounit, kHALOutputParam_Volume,
+ kAudioUnitScope_Global, 0, (float) sink->volume, 0);
+}
+
+static void
+gst_osx_audio_sink_select_device (GstOsxAudioSink * osxsink)
+{
+ OSStatus status;
+ UInt32 propertySize;
+
+ if (osxsink->device_id == kAudioDeviceUnknown) {
+ /* If no specific device has been selected by the user, then pick the
+ * default device */
+ GST_DEBUG_OBJECT (osxsink, "Selecting device for OSXAudioSink");
+ propertySize = sizeof (osxsink->device_id);
+ status =
+ AudioHardwareGetProperty (kAudioHardwarePropertyDefaultOutputDevice,
+ &propertySize, &osxsink->device_id);
+
+ if (status) {
+ GST_WARNING_OBJECT (osxsink,
+ "AudioHardwareGetProperty returned %d", (int) status);
+ } else {
+ GST_DEBUG_OBJECT (osxsink, "AudioHardwareGetProperty returned 0");
+ }
+
+ if (osxsink->device_id == kAudioDeviceUnknown) {
+ GST_WARNING_OBJECT (osxsink,
+ "AudioHardwareGetProperty: device_id is kAudioDeviceUnknown");
+ }
+
+ GST_DEBUG_OBJECT (osxsink, "AudioHardwareGetProperty: device_id is %lu",
+ (long) osxsink->device_id);
+ }
+}
diff --git a/sys/osxaudio/gstosxaudiosink.h b/sys/osxaudio/gstosxaudiosink.h
new file mode 100644
index 0000000..aac9719
--- /dev/null
+++ b/sys/osxaudio/gstosxaudiosink.h
@@ -0,0 +1,86 @@
+/*
+ * GStreamer
+ * Copyright (C) 2005-2006 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+ * Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.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.
+ *
+ * The development of this code was made possible due to the involvement of
+ * Pioneers of the Inevitable, the creators of the Songbird Music player
+ *
+ */
+
+#ifndef __GST_OSXAUDIOSINK_H__
+#define __GST_OSXAUDIOSINK_H__
+
+#include <gst/gst.h>
+#include <gst/audio/gstbaseaudiosink.h>
+#include "gstosxringbuffer.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSX_AUDIO_SINK \
+ (gst_osx_audio_sink_get_type())
+#define GST_OSX_AUDIO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSX_AUDIO_SINK,GstOsxAudioSink))
+#define GST_OSX_AUDIO_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSX_AUDIO_SINK,GstOsxAudioSinkClass))
+
+typedef struct _GstOsxAudioSink GstOsxAudioSink;
+typedef struct _GstOsxAudioSinkClass GstOsxAudioSinkClass;
+
+struct _GstOsxAudioSink
+{
+ GstBaseAudioSink sink;
+
+ AudioDeviceID device_id;
+ AudioUnit audiounit;
+ double volume;
+};
+
+struct _GstOsxAudioSinkClass
+{
+ GstBaseAudioSinkClass parent_class;
+};
+
+GType gst_osx_audio_sink_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OSXAUDIOSINK_H__ */
diff --git a/sys/osxaudio/gstosxaudiosrc.c b/sys/osxaudio/gstosxaudiosrc.c
new file mode 100644
index 0000000..7e9ad24
--- /dev/null
+++ b/sys/osxaudio/gstosxaudiosrc.c
@@ -0,0 +1,362 @@
+/*
+ * GStreamer
+ * Copyright (C) 2005,2006 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+ * Copyright (C) 2008 Pioneers of the Inevitable <songbird@songbirdnest.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-osxaudiosrc
+ *
+ * This element captures raw audio samples using the CoreAudio api.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch osxaudiosrc ! wavenc ! filesink location=audio.wav
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gst/gst.h>
+#include <CoreAudio/CoreAudio.h>
+#include <CoreAudio/AudioHardware.h>
+#include "gstosxaudiosrc.h"
+#include "gstosxaudioelement.h"
+
+GST_DEBUG_CATEGORY_STATIC (osx_audiosrc_debug);
+#define GST_CAT_DEFAULT osx_audiosrc_debug
+
+/* Filter signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum
+{
+ ARG_0,
+ ARG_DEVICE
+};
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-float, "
+ "endianness = (int) {" G_STRINGIFY (G_BYTE_ORDER) " }, "
+ "signed = (boolean) { TRUE }, "
+ "width = (int) 32, "
+ "depth = (int) 32, "
+ "rate = (int) [1, MAX], " "channels = (int) [1, MAX]")
+ );
+
+static void gst_osx_audio_src_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_osx_audio_src_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static GstCaps *gst_osx_audio_src_get_caps (GstBaseSrc * src);
+
+static GstRingBuffer *gst_osx_audio_src_create_ringbuffer (GstBaseAudioSrc *
+ src);
+static void gst_osx_audio_src_osxelement_init (gpointer g_iface,
+ gpointer iface_data);
+static OSStatus gst_osx_audio_src_io_proc (GstOsxRingBuffer * buf,
+ AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp, UInt32 inBusNumber,
+ UInt32 inNumberFrames, AudioBufferList * bufferList);
+static void gst_osx_audio_src_select_device (GstOsxAudioSrc * osxsrc);
+
+static void
+gst_osx_audio_src_do_init (GType type)
+{
+ static const GInterfaceInfo osxelement_info = {
+ gst_osx_audio_src_osxelement_init,
+ NULL,
+ NULL
+ };
+
+ GST_DEBUG_CATEGORY_INIT (osx_audiosrc_debug, "osxaudiosrc", 0,
+ "OSX Audio Src");
+ GST_DEBUG ("Adding static interface");
+ g_type_add_interface_static (type, GST_OSX_AUDIO_ELEMENT_TYPE,
+ &osxelement_info);
+}
+
+GST_BOILERPLATE_FULL (GstOsxAudioSrc, gst_osx_audio_src, GstBaseAudioSrc,
+ GST_TYPE_BASE_AUDIO_SRC, gst_osx_audio_src_do_init);
+
+static void
+gst_osx_audio_src_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_add_static_pad_template (element_class, &src_factory);
+
+ gst_element_class_set_details_simple (element_class, "Audio Source (OSX)",
+ "Source/Audio",
+ "Input from a sound card in OS X",
+ "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
+}
+
+static void
+gst_osx_audio_src_class_init (GstOsxAudioSrcClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSrcClass *gstbasesrc_class;
+ GstBaseAudioSrcClass *gstbaseaudiosrc_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesrc_class = (GstBaseSrcClass *) klass;
+ gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->set_property = gst_osx_audio_src_set_property;
+ gobject_class->get_property = gst_osx_audio_src_get_property;
+
+ gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_osx_audio_src_get_caps);
+
+ g_object_class_install_property (gobject_class, ARG_DEVICE,
+ g_param_spec_int ("device", "Device ID", "Device ID of input device",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ gstbaseaudiosrc_class->create_ringbuffer =
+ GST_DEBUG_FUNCPTR (gst_osx_audio_src_create_ringbuffer);
+}
+
+static void
+gst_osx_audio_src_init (GstOsxAudioSrc * src, GstOsxAudioSrcClass * gclass)
+{
+ gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
+
+ src->device_id = kAudioDeviceUnknown;
+ src->deviceChannels = -1;
+}
+
+static void
+gst_osx_audio_src_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOsxAudioSrc *src = GST_OSX_AUDIO_SRC (object);
+
+ switch (prop_id) {
+ case ARG_DEVICE:
+ src->device_id = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_osx_audio_src_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstOsxAudioSrc *src = GST_OSX_AUDIO_SRC (object);
+
+ switch (prop_id) {
+ case ARG_DEVICE:
+ g_value_set_int (value, src->device_id);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstCaps *
+gst_osx_audio_src_get_caps (GstBaseSrc * src)
+{
+ GstElementClass *gstelement_class;
+ GstOsxAudioSrc *osxsrc;
+ GstPadTemplate *pad_template;
+ GstCaps *caps;
+ gint min, max;
+
+ gstelement_class = GST_ELEMENT_GET_CLASS (src);
+ osxsrc = GST_OSX_AUDIO_SRC (src);
+
+ if (osxsrc->deviceChannels == -1) {
+ /* -1 means we don't know the number of channels yet. for now, return
+ * template caps.
+ */
+ return NULL;
+ }
+
+ max = osxsrc->deviceChannels;
+ if (max < 1)
+ max = 1; /* 0 channels means 1 channel? */
+
+ min = MIN (1, max);
+
+ pad_template = gst_element_class_get_pad_template (gstelement_class, "src");
+ g_return_val_if_fail (pad_template != NULL, NULL);
+
+ caps = gst_caps_copy (gst_pad_template_get_caps (pad_template));
+
+ if (min == max) {
+ gst_caps_set_simple (caps, "channels", G_TYPE_INT, max, NULL);
+ } else {
+ gst_caps_set_simple (caps, "channels", GST_TYPE_INT_RANGE, min, max, NULL);
+ }
+
+ return caps;
+}
+
+static GstRingBuffer *
+gst_osx_audio_src_create_ringbuffer (GstBaseAudioSrc * src)
+{
+ GstOsxAudioSrc *osxsrc;
+ GstOsxRingBuffer *ringbuffer;
+
+ osxsrc = GST_OSX_AUDIO_SRC (src);
+
+ gst_osx_audio_src_select_device (osxsrc);
+
+ GST_DEBUG ("Creating ringbuffer");
+ ringbuffer = g_object_new (GST_TYPE_OSX_RING_BUFFER, NULL);
+ GST_DEBUG ("osx src 0x%p element 0x%p ioproc 0x%p", osxsrc,
+ GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc),
+ (void *) gst_osx_audio_src_io_proc);
+
+ ringbuffer->element = GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc);
+ ringbuffer->is_src = TRUE;
+ ringbuffer->device_id = osxsrc->device_id;
+
+ return GST_RING_BUFFER (ringbuffer);
+}
+
+static OSStatus
+gst_osx_audio_src_io_proc (GstOsxRingBuffer * buf,
+ AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * bufferList)
+{
+ OSStatus status;
+ guint8 *writeptr;
+ gint writeseg;
+ gint len;
+ gint remaining;
+ gint offset = 0;
+
+ status = AudioUnitRender (buf->audiounit, ioActionFlags, inTimeStamp,
+ inBusNumber, inNumberFrames, buf->recBufferList);
+
+ if (status) {
+ GST_WARNING_OBJECT (buf, "AudioUnitRender returned %d", (int) status);
+ return status;
+ }
+
+ remaining = buf->recBufferList->mBuffers[0].mDataByteSize;
+
+ while (remaining) {
+ if (!gst_ring_buffer_prepare_read (GST_RING_BUFFER (buf),
+ &writeseg, &writeptr, &len))
+ return 0;
+
+ len -= buf->segoffset;
+
+ if (len > remaining)
+ len = remaining;
+
+ memcpy (writeptr + buf->segoffset,
+ (char *) buf->recBufferList->mBuffers[0].mData + offset, len);
+
+ buf->segoffset += len;
+ offset += len;
+ remaining -= len;
+
+ if ((gint) buf->segoffset == GST_RING_BUFFER (buf)->spec.segsize) {
+ /* we wrote one segment */
+ gst_ring_buffer_advance (GST_RING_BUFFER (buf), 1);
+
+ buf->segoffset = 0;
+ }
+ }
+ return 0;
+}
+
+static void
+gst_osx_audio_src_osxelement_init (gpointer g_iface, gpointer iface_data)
+{
+ GstOsxAudioElementInterface *iface = (GstOsxAudioElementInterface *) g_iface;
+
+ iface->io_proc = (AURenderCallback) gst_osx_audio_src_io_proc;
+}
+
+static void
+gst_osx_audio_src_select_device (GstOsxAudioSrc * osxsrc)
+{
+ OSStatus status;
+ UInt32 propertySize;
+
+ if (osxsrc->device_id == kAudioDeviceUnknown) {
+ /* If no specific device has been selected by the user, then pick the
+ * default device */
+ GST_DEBUG_OBJECT (osxsrc, "Selecting device for OSXAudioSrc");
+ propertySize = sizeof (osxsrc->device_id);
+ status = AudioHardwareGetProperty (kAudioHardwarePropertyDefaultInputDevice,
+ &propertySize, &osxsrc->device_id);
+
+ if (status) {
+ GST_WARNING_OBJECT (osxsrc,
+ "AudioHardwareGetProperty returned %d", (int) status);
+ } else {
+ GST_DEBUG_OBJECT (osxsrc, "AudioHardwareGetProperty returned 0");
+ }
+
+ if (osxsrc->device_id == kAudioDeviceUnknown) {
+ GST_WARNING_OBJECT (osxsrc,
+ "AudioHardwareGetProperty: device_id is kAudioDeviceUnknown");
+ }
+
+ GST_DEBUG_OBJECT (osxsrc, "AudioHardwareGetProperty: device_id is %lu",
+ (long) osxsrc->device_id);
+ }
+}
diff --git a/sys/osxaudio/gstosxaudiosrc.h b/sys/osxaudio/gstosxaudiosrc.h
new file mode 100644
index 0000000..a812d9e
--- /dev/null
+++ b/sys/osxaudio/gstosxaudiosrc.h
@@ -0,0 +1,82 @@
+/*
+ * GStreamer
+ * Copyright (C) 2005-2006 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+ *
+ * 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.
+ */
+
+#ifndef __GST_OSXAUDIOSRC_H__
+#define __GST_OSXAUDIOSRC_H__
+
+#include <gst/gst.h>
+#include <gst/audio/gstbaseaudiosrc.h>
+#include "gstosxringbuffer.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSX_AUDIO_SRC \
+ (gst_osx_audio_src_get_type())
+#define GST_OSX_AUDIO_SRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSX_AUDIO_SRC,GstOsxAudioSrc))
+#define GST_OSX_AUDIO_SRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSX_AUDIO_SRC,GstOsxAudioSrcClass))
+
+typedef struct _GstOsxAudioSrc GstOsxAudioSrc;
+typedef struct _GstOsxAudioSrcClass GstOsxAudioSrcClass;
+
+struct _GstOsxAudioSrc
+{
+ GstBaseAudioSrc src;
+
+ AudioDeviceID device_id;
+
+ /* actual number of channels reported by input device */
+ int deviceChannels;
+};
+
+struct _GstOsxAudioSrcClass
+{
+ GstBaseAudioSrcClass parent_class;
+};
+
+GType gst_osx_audio_src_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OSXAUDIOSRC_H__ */
diff --git a/sys/osxaudio/gstosxringbuffer.c b/sys/osxaudio/gstosxringbuffer.c
new file mode 100644
index 0000000..095efc1
--- /dev/null
+++ b/sys/osxaudio/gstosxringbuffer.c
@@ -0,0 +1,689 @@
+/*
+ * GStreamer
+ * Copyright (C) 2006 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+ * Copyright (C) 2008 Pioneers of the Inevitable <songbird@songbirdnest.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.
+ */
+
+#include <CoreAudio/CoreAudio.h>
+#include <CoreServices/CoreServices.h>
+#include <gst/gst.h>
+#include <gst/audio/multichannel.h>
+#include "gstosxringbuffer.h"
+#include "gstosxaudiosink.h"
+#include "gstosxaudiosrc.h"
+
+GST_DEBUG_CATEGORY_STATIC (osx_audio_debug);
+#define GST_CAT_DEFAULT osx_audio_debug
+
+static void gst_osx_ring_buffer_dispose (GObject * object);
+static void gst_osx_ring_buffer_finalize (GObject * object);
+static gboolean gst_osx_ring_buffer_open_device (GstRingBuffer * buf);
+static gboolean gst_osx_ring_buffer_close_device (GstRingBuffer * buf);
+
+static gboolean gst_osx_ring_buffer_acquire (GstRingBuffer * buf,
+ GstRingBufferSpec * spec);
+static gboolean gst_osx_ring_buffer_release (GstRingBuffer * buf);
+
+static gboolean gst_osx_ring_buffer_start (GstRingBuffer * buf);
+static gboolean gst_osx_ring_buffer_pause (GstRingBuffer * buf);
+static gboolean gst_osx_ring_buffer_stop (GstRingBuffer * buf);
+static guint gst_osx_ring_buffer_delay (GstRingBuffer * buf);
+static GstRingBufferClass *ring_parent_class = NULL;
+
+static OSStatus gst_osx_ring_buffer_render_notify (GstOsxRingBuffer * osxbuf,
+ AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp, unsigned int inBusNumber,
+ unsigned int inNumberFrames, AudioBufferList * ioData);
+
+static AudioBufferList *buffer_list_alloc (int channels, int size);
+static void buffer_list_free (AudioBufferList * list);
+
+static void
+gst_osx_ring_buffer_do_init (GType type)
+{
+ GST_DEBUG_CATEGORY_INIT (osx_audio_debug, "osxaudio", 0,
+ "OSX Audio Elements");
+}
+
+GST_BOILERPLATE_FULL (GstOsxRingBuffer, gst_osx_ring_buffer, GstRingBuffer,
+ GST_TYPE_RING_BUFFER, gst_osx_ring_buffer_do_init);
+
+static void
+gst_osx_ring_buffer_base_init (gpointer g_class)
+{
+ /* Nothing to do right now */
+}
+
+static void
+gst_osx_ring_buffer_class_init (GstOsxRingBufferClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstObjectClass *gstobject_class;
+ GstRingBufferClass *gstringbuffer_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstobject_class = (GstObjectClass *) klass;
+ gstringbuffer_class = (GstRingBufferClass *) klass;
+
+ ring_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->dispose = gst_osx_ring_buffer_dispose;
+ gobject_class->finalize = gst_osx_ring_buffer_finalize;
+
+ gstringbuffer_class->open_device =
+ GST_DEBUG_FUNCPTR (gst_osx_ring_buffer_open_device);
+ gstringbuffer_class->close_device =
+ GST_DEBUG_FUNCPTR (gst_osx_ring_buffer_close_device);
+ gstringbuffer_class->acquire =
+ GST_DEBUG_FUNCPTR (gst_osx_ring_buffer_acquire);
+ gstringbuffer_class->release =
+ GST_DEBUG_FUNCPTR (gst_osx_ring_buffer_release);
+ gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_osx_ring_buffer_start);
+ gstringbuffer_class->pause = GST_DEBUG_FUNCPTR (gst_osx_ring_buffer_pause);
+ gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_osx_ring_buffer_start);
+ gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_osx_ring_buffer_stop);
+
+ gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_osx_ring_buffer_delay);
+
+ GST_DEBUG ("osx ring buffer class init");
+}
+
+static void
+gst_osx_ring_buffer_init (GstOsxRingBuffer * ringbuffer,
+ GstOsxRingBufferClass * g_class)
+{
+ /* Nothing to do right now */
+}
+
+static void
+gst_osx_ring_buffer_dispose (GObject * object)
+{
+ G_OBJECT_CLASS (ring_parent_class)->dispose (object);
+}
+
+static void
+gst_osx_ring_buffer_finalize (GObject * object)
+{
+ G_OBJECT_CLASS (ring_parent_class)->finalize (object);
+}
+
+static AudioUnit
+gst_osx_ring_buffer_create_audio_unit (GstOsxRingBuffer * osxbuf,
+ gboolean input, AudioDeviceID device_id)
+{
+ ComponentDescription desc;
+ Component comp;
+ OSStatus status;
+ AudioUnit unit;
+ UInt32 enableIO;
+
+ /* Create a HALOutput AudioUnit.
+ * This is the lowest-level output API that is actually sensibly usable
+ * (the lower level ones require that you do channel-remapping yourself,
+ * and the CoreAudio channel mapping is sufficiently complex that doing
+ * so would be very difficult)
+ *
+ * Note that for input we request an output unit even though we will do
+ * input with it: http://developer.apple.com/technotes/tn2002/tn2091.html
+ */
+ desc.componentType = kAudioUnitType_Output;
+ desc.componentSubType = kAudioUnitSubType_HALOutput;
+ desc.componentManufacturer = kAudioUnitManufacturer_Apple;
+ desc.componentFlags = 0;
+ desc.componentFlagsMask = 0;
+
+ comp = FindNextComponent (NULL, &desc);
+ if (comp == NULL) {
+ GST_WARNING_OBJECT (osxbuf, "Couldn't find HALOutput component");
+ return NULL;
+ }
+
+ status = OpenAComponent (comp, &unit);
+
+ if (status) {
+ GST_WARNING_OBJECT (osxbuf, "Couldn't open HALOutput component");
+ return NULL;
+ }
+
+ if (input) {
+ /* enable input */
+ enableIO = 1;
+ status = AudioUnitSetProperty (unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, /* 1 = input element */
+ &enableIO, sizeof (enableIO));
+
+ if (status) {
+ CloseComponent (unit);
+ GST_WARNING_OBJECT (osxbuf, "Failed to enable input: %lx",
+ (gulong) status);
+ return NULL;
+ }
+
+ /* disable output */
+ enableIO = 0;
+ status = AudioUnitSetProperty (unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, /* 0 = output element */
+ &enableIO, sizeof (enableIO));
+
+ if (status) {
+ CloseComponent (unit);
+ GST_WARNING_OBJECT (osxbuf, "Failed to disable output: %lx",
+ (gulong) status);
+ return NULL;
+ }
+ }
+
+ /* Specify which device we're using. */
+ GST_DEBUG_OBJECT (osxbuf, "Setting device to %d", (int) device_id);
+ status = AudioUnitSetProperty (unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, /* N/A for global */
+ &device_id, sizeof (AudioDeviceID));
+
+ if (status) {
+ CloseComponent (unit);
+ GST_WARNING_OBJECT (osxbuf, "Failed to set device: %lx", (gulong) status);
+ return NULL;
+ }
+
+ GST_DEBUG_OBJECT (osxbuf, "Create HALOutput AudioUnit: %p", unit);
+
+ return unit;
+}
+
+static gboolean
+gst_osx_ring_buffer_open_device (GstRingBuffer * buf)
+{
+ GstOsxRingBuffer *osxbuf;
+ GstOsxAudioSink *sink;
+ GstOsxAudioSrc *src;
+ AudioStreamBasicDescription asbd_in;
+ OSStatus status;
+ UInt32 propertySize;
+
+ osxbuf = GST_OSX_RING_BUFFER (buf);
+ sink = NULL;
+ src = NULL;
+
+ osxbuf->audiounit = gst_osx_ring_buffer_create_audio_unit (osxbuf,
+ osxbuf->is_src, osxbuf->device_id);
+
+ if (osxbuf->is_src) {
+ src = GST_OSX_AUDIO_SRC (GST_OBJECT_PARENT (buf));
+
+ propertySize = sizeof (asbd_in);
+ status = AudioUnitGetProperty (osxbuf->audiounit,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input, 1, &asbd_in, &propertySize);
+
+ if (status) {
+ CloseComponent (osxbuf->audiounit);
+ osxbuf->audiounit = NULL;
+ GST_WARNING_OBJECT (osxbuf, "Unable to obtain device properties: %lx",
+ (gulong) status);
+ return FALSE;
+ }
+
+ src->deviceChannels = asbd_in.mChannelsPerFrame;
+ } else {
+ sink = GST_OSX_AUDIO_SINK (GST_OBJECT_PARENT (buf));
+
+ /* needed for the sink's volume control */
+ sink->audiounit = osxbuf->audiounit;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_osx_ring_buffer_close_device (GstRingBuffer * buf)
+{
+ GstOsxRingBuffer *osxbuf;
+ osxbuf = GST_OSX_RING_BUFFER (buf);
+
+ CloseComponent (osxbuf->audiounit);
+ osxbuf->audiounit = NULL;
+
+ return TRUE;
+}
+
+static AudioChannelLabel
+gst_audio_channel_position_to_coreaudio_channel_label (GstAudioChannelPosition
+ position, int channel)
+{
+ switch (position) {
+ case GST_AUDIO_CHANNEL_POSITION_NONE:
+ return kAudioChannelLabel_Discrete_0 | channel;
+ case GST_AUDIO_CHANNEL_POSITION_FRONT_MONO:
+ return kAudioChannelLabel_Mono;
+ case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT:
+ return kAudioChannelLabel_Left;
+ case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT:
+ return kAudioChannelLabel_Right;
+ case GST_AUDIO_CHANNEL_POSITION_REAR_CENTER:
+ return kAudioChannelLabel_CenterSurround;
+ case GST_AUDIO_CHANNEL_POSITION_REAR_LEFT:
+ return kAudioChannelLabel_LeftSurround;
+ case GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT:
+ return kAudioChannelLabel_RightSurround;
+ case GST_AUDIO_CHANNEL_POSITION_LFE:
+ return kAudioChannelLabel_LFEScreen;
+ case GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER:
+ return kAudioChannelLabel_Center;
+ case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
+ return kAudioChannelLabel_Center; // ???
+ case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
+ return kAudioChannelLabel_Center; // ???
+ case GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT:
+ return kAudioChannelLabel_LeftSurroundDirect;
+ case GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT:
+ return kAudioChannelLabel_RightSurroundDirect;
+ default:
+ return kAudioChannelLabel_Unknown;
+ }
+}
+
+static gboolean
+gst_osx_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
+{
+ /* Configure the output stream and allocate ringbuffer memory */
+ GstOsxRingBuffer *osxbuf;
+ AudioStreamBasicDescription format;
+ AudioChannelLayout *layout = NULL;
+ OSStatus status;
+ UInt32 propertySize;
+ int layoutSize;
+ int element;
+ int i;
+ AudioUnitScope scope;
+ gboolean ret = FALSE;
+ GstStructure *structure;
+ GstAudioChannelPosition *positions;
+ UInt32 frameSize;
+
+ osxbuf = GST_OSX_RING_BUFFER (buf);
+
+ /* Fill out the audio description we're going to be using */
+ format.mFormatID = kAudioFormatLinearPCM;
+ format.mSampleRate = (double) spec->rate;
+ format.mChannelsPerFrame = spec->channels;
+ format.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
+ format.mBytesPerFrame = spec->channels * sizeof (float);
+ format.mBitsPerChannel = sizeof (float) * 8;
+ format.mBytesPerPacket = spec->channels * sizeof (float);
+ format.mFramesPerPacket = 1;
+ format.mReserved = 0;
+
+ /* Describe channels */
+ layoutSize = sizeof (AudioChannelLayout) +
+ spec->channels * sizeof (AudioChannelDescription);
+ layout = g_malloc (layoutSize);
+
+ structure = gst_caps_get_structure (spec->caps, 0);
+ positions = gst_audio_get_channel_positions (structure);
+
+ layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
+ layout->mChannelBitmap = 0; /* Not used */
+ layout->mNumberChannelDescriptions = spec->channels;
+ for (i = 0; i < spec->channels; i++) {
+ if (positions) {
+ layout->mChannelDescriptions[i].mChannelLabel =
+ gst_audio_channel_position_to_coreaudio_channel_label (positions[i],
+ i);
+ } else {
+ /* Discrete channel numbers are ORed into this */
+ layout->mChannelDescriptions[i].mChannelLabel =
+ kAudioChannelLabel_Discrete_0 | i;
+ }
+
+ /* Others unused */
+ layout->mChannelDescriptions[i].mChannelFlags = 0;
+ layout->mChannelDescriptions[i].mCoordinates[0] = 0.f;
+ layout->mChannelDescriptions[i].mCoordinates[1] = 0.f;
+ layout->mChannelDescriptions[i].mCoordinates[2] = 0.f;
+ }
+
+ if (positions) {
+ g_free (positions);
+ positions = NULL;
+ }
+
+ GST_LOG_OBJECT (osxbuf, "Format: %x, %f, %u, %x, %d, %d, %d, %d, %d",
+ (unsigned int) format.mFormatID,
+ format.mSampleRate,
+ (unsigned int) format.mChannelsPerFrame,
+ (unsigned int) format.mFormatFlags,
+ (unsigned int) format.mBytesPerFrame,
+ (unsigned int) format.mBitsPerChannel,
+ (unsigned int) format.mBytesPerPacket,
+ (unsigned int) format.mFramesPerPacket, (unsigned int) format.mReserved);
+
+ GST_DEBUG_OBJECT (osxbuf, "Setting format for AudioUnit");
+
+ scope = osxbuf->is_src ? kAudioUnitScope_Output : kAudioUnitScope_Input;
+ element = osxbuf->is_src ? 1 : 0;
+
+ propertySize = sizeof (format);
+ status = AudioUnitSetProperty (osxbuf->audiounit,
+ kAudioUnitProperty_StreamFormat, scope, element, &format, propertySize);
+
+ if (status) {
+ GST_WARNING_OBJECT (osxbuf, "Failed to set audio description: %lx",
+ (gulong) status);
+ goto done;
+ }
+
+ status = AudioUnitSetProperty (osxbuf->audiounit,
+ kAudioUnitProperty_AudioChannelLayout,
+ scope, element, layout, layoutSize);
+ if (status) {
+ GST_WARNING_OBJECT (osxbuf, "Failed to set output channel layout: %lx",
+ (gulong) status);
+ goto done;
+ }
+
+ spec->segsize =
+ (spec->latency_time * spec->rate / G_USEC_PER_SEC) *
+ spec->bytes_per_sample;
+ spec->segtotal = spec->buffer_time / spec->latency_time;
+
+ /* create AudioBufferList needed for recording */
+ if (osxbuf->is_src) {
+ propertySize = sizeof (frameSize);
+ status = AudioUnitGetProperty (osxbuf->audiounit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, 0, /* N/A for global */
+ &frameSize, &propertySize);
+
+ if (status) {
+ GST_WARNING_OBJECT (osxbuf, "Failed to get frame size: %lx",
+ (gulong) status);
+ goto done;
+ }
+
+ osxbuf->recBufferList = buffer_list_alloc (format.mChannelsPerFrame,
+ frameSize * format.mBytesPerFrame);
+ }
+
+ buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize);
+ memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data));
+
+ osxbuf->segoffset = 0;
+
+ status = AudioUnitInitialize (osxbuf->audiounit);
+ if (status) {
+ gst_buffer_unref (buf->data);
+ buf->data = NULL;
+
+ if (osxbuf->recBufferList) {
+ buffer_list_free (osxbuf->recBufferList);
+ osxbuf->recBufferList = NULL;
+ }
+
+ GST_WARNING_OBJECT (osxbuf,
+ "Failed to initialise AudioUnit: %d", (int) status);
+ goto done;
+ }
+
+ GST_DEBUG_OBJECT (osxbuf, "osx ring buffer acquired");
+
+ ret = TRUE;
+
+done:
+ g_free (layout);
+ return ret;
+}
+
+static gboolean
+gst_osx_ring_buffer_release (GstRingBuffer * buf)
+{
+ GstOsxRingBuffer *osxbuf;
+
+ osxbuf = GST_OSX_RING_BUFFER (buf);
+
+ AudioUnitUninitialize (osxbuf->audiounit);
+
+ gst_buffer_unref (buf->data);
+ buf->data = NULL;
+
+ if (osxbuf->recBufferList) {
+ buffer_list_free (osxbuf->recBufferList);
+ osxbuf->recBufferList = NULL;
+ }
+
+ return TRUE;
+}
+
+static void
+gst_osx_ring_buffer_remove_render_callback (GstOsxRingBuffer * osxbuf)
+{
+ AURenderCallbackStruct input;
+ OSStatus status;
+
+ /* Deactivate the render callback by calling SetRenderCallback with a NULL
+ * inputProc.
+ */
+ input.inputProc = NULL;
+ input.inputProcRefCon = NULL;
+
+ status = AudioUnitSetProperty (osxbuf->audiounit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, /* N/A for global */
+ &input, sizeof (input));
+
+ if (status) {
+ GST_WARNING_OBJECT (osxbuf, "Failed to remove render callback");
+ }
+
+ /* Remove the RenderNotify too */
+ status = AudioUnitRemoveRenderNotify (osxbuf->audiounit,
+ (AURenderCallback) gst_osx_ring_buffer_render_notify, osxbuf);
+
+ if (status) {
+ GST_WARNING_OBJECT (osxbuf, "Failed to remove render notify callback");
+ }
+
+ /* We're deactivated.. */
+ osxbuf->io_proc_needs_deactivation = FALSE;
+ osxbuf->io_proc_active = FALSE;
+}
+
+static OSStatus
+gst_osx_ring_buffer_render_notify (GstOsxRingBuffer * osxbuf,
+ AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ unsigned int inBusNumber,
+ unsigned int inNumberFrames, AudioBufferList * ioData)
+{
+ /* Before rendering a frame, we get the PreRender notification.
+ * Here, we detach the RenderCallback if we've been paused.
+ *
+ * This is necessary (rather than just directly detaching it) to work
+ * around some thread-safety issues in CoreAudio
+ */
+ if ((*ioActionFlags) & kAudioUnitRenderAction_PreRender) {
+ if (osxbuf->io_proc_needs_deactivation) {
+ gst_osx_ring_buffer_remove_render_callback (osxbuf);
+ }
+ }
+
+ return noErr;
+}
+
+static gboolean
+gst_osx_ring_buffer_start (GstRingBuffer * buf)
+{
+ OSStatus status;
+ GstOsxRingBuffer *osxbuf;
+ AURenderCallbackStruct input;
+ AudioUnitPropertyID callback_type;
+
+ osxbuf = GST_OSX_RING_BUFFER (buf);
+
+ GST_DEBUG ("osx ring buffer start ioproc: 0x%p device_id %lu",
+ osxbuf->element->io_proc, (gulong) osxbuf->device_id);
+ if (!osxbuf->io_proc_active) {
+ callback_type = osxbuf->is_src ?
+ kAudioOutputUnitProperty_SetInputCallback :
+ kAudioUnitProperty_SetRenderCallback;
+
+ input.inputProc = (AURenderCallback) osxbuf->element->io_proc;
+ input.inputProcRefCon = osxbuf;
+
+ status = AudioUnitSetProperty (osxbuf->audiounit, callback_type, kAudioUnitScope_Global, 0, /* N/A for global */
+ &input, sizeof (input));
+
+ if (status) {
+ GST_WARNING ("AudioUnitSetProperty returned %d", (int) status);
+ return FALSE;
+ }
+ // ### does it make sense to do this notify stuff for input mode?
+ status = AudioUnitAddRenderNotify (osxbuf->audiounit,
+ (AURenderCallback) gst_osx_ring_buffer_render_notify, osxbuf);
+
+ if (status) {
+ GST_WARNING ("AudioUnitAddRenderNotify returned %d", (int) status);
+ return FALSE;
+ }
+
+ osxbuf->io_proc_active = TRUE;
+ }
+
+ osxbuf->io_proc_needs_deactivation = FALSE;
+
+ status = AudioOutputUnitStart (osxbuf->audiounit);
+ if (status) {
+ GST_WARNING ("AudioOutputUnitStart returned %d", (int) status);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// ###
+static gboolean
+gst_osx_ring_buffer_pause (GstRingBuffer * buf)
+{
+ GstOsxRingBuffer *osxbuf = GST_OSX_RING_BUFFER (buf);
+
+ GST_DEBUG ("osx ring buffer pause ioproc: 0x%p device_id %lu",
+ osxbuf->element->io_proc, (gulong) osxbuf->device_id);
+ if (osxbuf->io_proc_active) {
+ /* CoreAudio isn't threadsafe enough to do this here; we must deactivate
+ * the render callback elsewhere. See:
+ * http://lists.apple.com/archives/Coreaudio-api/2006/Mar/msg00010.html
+ */
+ osxbuf->io_proc_needs_deactivation = TRUE;
+ }
+ return TRUE;
+}
+
+// ###
+static gboolean
+gst_osx_ring_buffer_stop (GstRingBuffer * buf)
+{
+ OSErr status;
+ GstOsxRingBuffer *osxbuf;
+
+ osxbuf = GST_OSX_RING_BUFFER (buf);
+
+ GST_DEBUG ("osx ring buffer stop ioproc: 0x%p device_id %lu",
+ osxbuf->element->io_proc, (gulong) osxbuf->device_id);
+
+ status = AudioOutputUnitStop (osxbuf->audiounit);
+ if (status)
+ GST_WARNING ("AudioOutputUnitStop returned %d", (int) status);
+
+ // ###: why is it okay to directly remove from here but not from pause() ?
+ if (osxbuf->io_proc_active) {
+ gst_osx_ring_buffer_remove_render_callback (osxbuf);
+ }
+ return TRUE;
+}
+
+static guint
+gst_osx_ring_buffer_delay (GstRingBuffer * buf)
+{
+ double latency;
+ UInt32 size = sizeof (double);
+ GstOsxRingBuffer *osxbuf;
+ OSStatus status;
+ guint samples;
+
+ osxbuf = GST_OSX_RING_BUFFER (buf);
+
+ status = AudioUnitGetProperty (osxbuf->audiounit, kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0, /* N/A for global */
+ &latency, &size);
+
+ if (status) {
+ GST_WARNING_OBJECT (buf, "Failed to get latency: %d", (int) status);
+ return 0;
+ }
+
+ samples = latency * GST_RING_BUFFER (buf)->spec.rate;
+ GST_DEBUG_OBJECT (buf, "Got latency: %f seconds -> %d samples", latency,
+ samples);
+ return samples;
+}
+
+static AudioBufferList *
+buffer_list_alloc (int channels, int size)
+{
+ AudioBufferList *list;
+ int total_size;
+ int n;
+
+ total_size = sizeof (AudioBufferList) + 1 * sizeof (AudioBuffer);
+ list = (AudioBufferList *) g_malloc (total_size);
+
+ list->mNumberBuffers = 1;
+ for (n = 0; n < (int) list->mNumberBuffers; ++n) {
+ list->mBuffers[n].mNumberChannels = channels;
+ list->mBuffers[n].mDataByteSize = size;
+ list->mBuffers[n].mData = g_malloc (size);
+ }
+
+ return list;
+}
+
+static void
+buffer_list_free (AudioBufferList * list)
+{
+ int n;
+
+ for (n = 0; n < (int) list->mNumberBuffers; ++n) {
+ if (list->mBuffers[n].mData)
+ g_free (list->mBuffers[n].mData);
+ }
+
+ g_free (list);
+}
diff --git a/sys/osxaudio/gstosxringbuffer.h b/sys/osxaudio/gstosxringbuffer.h
new file mode 100644
index 0000000..5e6dbe4
--- /dev/null
+++ b/sys/osxaudio/gstosxringbuffer.h
@@ -0,0 +1,94 @@
+/*
+ * GStreamer
+ * Copyright (C) 2006 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+ *
+ * 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.
+ */
+
+#ifndef __GST_OSX_RING_BUFFER_H__
+#define __GST_OSX_RING_BUFFER_H__
+
+#include <gst/gst.h>
+#include <gst/audio/gstringbuffer.h>
+#include <CoreAudio/CoreAudio.h>
+#include "gstosxaudioelement.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSX_RING_BUFFER \
+ (gst_osx_ring_buffer_get_type())
+#define GST_OSX_RING_BUFFER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSX_RING_BUFFER,GstOsxRingBuffer))
+#define GST_OSX_RING_BUFFER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSX_RING_BUFFER,GstOsxRingBufferClass))
+#define GST_OSX_RING_BUFFER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OSX_RING_BUFFER,GstOsxRingBufferClass))
+#define GST_IS_OSX_RING_BUFFER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSX_RING_BUFFER))
+#define GST_IS_OSX_RING_BUFFER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSX_RING_BUFFER))
+
+typedef struct _GstOsxRingBuffer GstOsxRingBuffer;
+typedef struct _GstOsxRingBufferClass GstOsxRingBufferClass;
+
+struct _GstOsxRingBuffer
+{
+ GstRingBuffer object;
+
+ gboolean is_src;
+ AudioUnit audiounit;
+ AudioDeviceID device_id;
+ gboolean io_proc_active;
+ gboolean io_proc_needs_deactivation;
+ guint buffer_len;
+ guint segoffset;
+ AudioBufferList * recBufferList;
+ GstOsxAudioElementInterface * element;
+};
+
+struct _GstOsxRingBufferClass
+{
+ GstRingBufferClass parent_class;
+};
+
+GType gst_osx_ring_buffer_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OSX_RING_BUFFER_H__ */
diff --git a/sys/osxvideo/Makefile.am b/sys/osxvideo/Makefile.am
new file mode 100644
index 0000000..8893c2e
--- /dev/null
+++ b/sys/osxvideo/Makefile.am
@@ -0,0 +1,19 @@
+
+plugin_LTLIBRARIES = libgstosxvideosink.la
+
+libgstosxvideosink_la_SOURCES = osxvideosink.m cocoawindow.m
+libgstosxvideosink_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \
+ $(GST_PLUGINS_BASE_CFLAGS)
+libgstosxvideosink_la_LIBADD = \
+ $(GST_LIBS) \
+ $(GST_BASE_LIBS) \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstvideo-$(GST_MAJORMINOR) \
+ -lgstinterfaces-$(GST_MAJORMINOR)
+
+libgstosxvideosink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -Wl,-framework -Wl,Cocoa -Wl,-framework -Wl,QuickTime -Wl,-framework -Wl,OpenGL
+libgstosxvideosink_la_LIBTOOLFLAGS = --tag=disable-static
+
+AM_OBJCFLAGS=$(CFLAGS) $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) -Wno-aggregate-return
+
+noinst_HEADERS = osxvideosink.h cocoawindow.h
diff --git a/sys/osxvideo/Makefile.in b/sys/osxvideo/Makefile.in
new file mode 100644
index 0000000..fe62cb4
--- /dev/null
+++ b/sys/osxvideo/Makefile.in
@@ -0,0 +1,824 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sys/osxvideo
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
+ $(top_srcdir)/common/m4/as-auto-alt.m4 \
+ $(top_srcdir)/common/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/common/m4/as-gcc-inline-assembly.m4 \
+ $(top_srcdir)/common/m4/as-objc.m4 \
+ $(top_srcdir)/common/m4/as-python.m4 \
+ $(top_srcdir)/common/m4/as-scrub-include.m4 \
+ $(top_srcdir)/common/m4/as-version.m4 \
+ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
+ $(top_srcdir)/common/m4/gst-arch.m4 \
+ $(top_srcdir)/common/m4/gst-args.m4 \
+ $(top_srcdir)/common/m4/gst-check.m4 \
+ $(top_srcdir)/common/m4/gst-default.m4 \
+ $(top_srcdir)/common/m4/gst-dowhile.m4 \
+ $(top_srcdir)/common/m4/gst-error.m4 \
+ $(top_srcdir)/common/m4/gst-feature.m4 \
+ $(top_srcdir)/common/m4/gst-gettext.m4 \
+ $(top_srcdir)/common/m4/gst-glib2.m4 \
+ $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \
+ $(top_srcdir)/common/m4/gst-platform.m4 \
+ $(top_srcdir)/common/m4/gst-plugin-docs.m4 \
+ $(top_srcdir)/common/m4/gst-plugindir.m4 \
+ $(top_srcdir)/common/m4/gst-x11.m4 \
+ $(top_srcdir)/common/m4/gst.m4 \
+ $(top_srcdir)/common/m4/gtk-doc.m4 \
+ $(top_srcdir)/common/m4/orc.m4 $(top_srcdir)/common/m4/pkg.m4 \
+ $(top_srcdir)/m4/aalib.m4 $(top_srcdir)/m4/esd.m4 \
+ $(top_srcdir)/m4/gconf-2.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gst-fionread.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgstosxvideosink_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libgstosxvideosink_la_OBJECTS = \
+ libgstosxvideosink_la-osxvideosink.lo \
+ libgstosxvideosink_la-cocoawindow.lo
+libgstosxvideosink_la_OBJECTS = $(am_libgstosxvideosink_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libgstosxvideosink_la_LINK = $(LIBTOOL) $(AM_V_lt) \
+ $(libgstosxvideosink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(OBJCLD) $(AM_OBJCFLAGS) $(OBJCFLAGS) \
+ $(libgstosxvideosink_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+OBJCCOMPILE = $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS)
+LTOBJCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_OBJCFLAGS) $(OBJCFLAGS)
+AM_V_OBJC = $(am__v_OBJC_@AM_V@)
+am__v_OBJC_ = $(am__v_OBJC_@AM_DEFAULT_V@)
+am__v_OBJC_0 = @echo " OBJC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+OBJCLD = $(OBJC)
+OBJCLINK = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(OBJCLD) $(AM_OBJCFLAGS) $(OBJCFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_OBJCLD = $(am__v_OBJCLD_@AM_V@)
+am__v_OBJCLD_ = $(am__v_OBJCLD_@AM_DEFAULT_V@)
+am__v_OBJCLD_0 = @echo " OBJCLD" $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libgstosxvideosink_la_SOURCES)
+DIST_SOURCES = $(libgstosxvideosink_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+AALIB_CFLAGS = @AALIB_CFLAGS@
+AALIB_CONFIG = @AALIB_CONFIG@
+AALIB_LIBS = @AALIB_LIBS@
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+ANNODEX_CFLAGS = @ANNODEX_CFLAGS@
+ANNODEX_LIBS = @ANNODEX_LIBS@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BZ2_LIBS = @BZ2_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_GOBJECT_CFLAGS = @CAIRO_GOBJECT_CFLAGS@
+CAIRO_GOBJECT_LIBS = @CAIRO_GOBJECT_LIBS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@
+DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@
+DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@
+DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@
+DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@
+DIRECTSOUND_CFLAGS = @DIRECTSOUND_CFLAGS@
+DIRECTSOUND_LDFLAGS = @DIRECTSOUND_LDFLAGS@
+DIRECTSOUND_LIBS = @DIRECTSOUND_LIBS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DV1394_CFLAGS = @DV1394_CFLAGS@
+DV1394_LIBS = @DV1394_LIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ERROR_CFLAGS = @ERROR_CFLAGS@
+ERROR_CXXFLAGS = @ERROR_CXXFLAGS@
+ESD_CFLAGS = @ESD_CFLAGS@
+ESD_CONFIG = @ESD_CONFIG@
+ESD_LIBS = @ESD_LIBS@
+EXEEXT = @EXEEXT@
+FFLAGS = @FFLAGS@
+FGREP = @FGREP@
+FLAC_CFLAGS = @FLAC_CFLAGS@
+FLAC_LIBS = @FLAC_LIBS@
+GCONFTOOL = @GCONFTOOL@
+GCONF_CFLAGS = @GCONF_CFLAGS@
+GCONF_LIBS = @GCONF_LIBS@
+GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+GCOV = @GCOV@
+GCOV_CFLAGS = @GCOV_CFLAGS@
+GCOV_LIBS = @GCOV_LIBS@
+GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@
+GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_PREFIX = @GLIB_PREFIX@
+GLIB_REQ = @GLIB_REQ@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@
+GSTPB_PREFIX = @GSTPB_PREFIX@
+GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@
+GST_BASE_CFLAGS = @GST_BASE_CFLAGS@
+GST_BASE_LIBS = @GST_BASE_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_CONTROLLER_CFLAGS = @GST_CONTROLLER_CFLAGS@
+GST_CONTROLLER_LIBS = @GST_CONTROLLER_LIBS@
+GST_CXXFLAGS = @GST_CXXFLAGS@
+GST_GDP_CFLAGS = @GST_GDP_CFLAGS@
+GST_GDP_LIBS = @GST_GDP_LIBS@
+GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@
+GST_LIBS = @GST_LIBS@
+GST_LICENSE = @GST_LICENSE@
+GST_LT_LDFLAGS = @GST_LT_LDFLAGS@
+GST_MAJORMINOR = @GST_MAJORMINOR@
+GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@
+GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@
+GST_PACKAGE_NAME = @GST_PACKAGE_NAME@
+GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@
+GST_PLUGINS_ALL = @GST_PLUGINS_ALL@
+GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@
+GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@
+GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@
+GST_PLUGINS_DIR = @GST_PLUGINS_DIR@
+GST_PLUGINS_SELECTED = @GST_PLUGINS_SELECTED@
+GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@
+GST_PREFIX = @GST_PREFIX@
+GST_TOOLS_DIR = @GST_TOOLS_DIR@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_X11_CFLAGS = @GTK_X11_CFLAGS@
+GTK_X11_LIBS = @GTK_X11_LIBS@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+HAVE_AVC1394 = @HAVE_AVC1394@
+HAVE_BZ2 = @HAVE_BZ2@
+HAVE_CXX = @HAVE_CXX@
+HAVE_DIRECTSOUND = @HAVE_DIRECTSOUND@
+HAVE_GCONFTOOL = @HAVE_GCONFTOOL@
+HAVE_ROM1394 = @HAVE_ROM1394@
+HAVE_SPEEX = @HAVE_SPEEX@
+HAVE_X = @HAVE_X@
+HAVE_XSHM = @HAVE_XSHM@
+HAVE_ZLIB = @HAVE_ZLIB@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JACK_0_120_1_CFLAGS = @JACK_0_120_1_CFLAGS@
+JACK_0_120_1_LIBS = @JACK_0_120_1_LIBS@
+JACK_1_9_7_CFLAGS = @JACK_1_9_7_CFLAGS@
+JACK_1_9_7_LIBS = @JACK_1_9_7_LIBS@
+JACK_CFLAGS = @JACK_CFLAGS@
+JACK_LIBS = @JACK_LIBS@
+JPEG_LIBS = @JPEG_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCACA_CFLAGS = @LIBCACA_CFLAGS@
+LIBCACA_LIBS = @LIBCACA_LIBS@
+LIBDV_CFLAGS = @LIBDV_CFLAGS@
+LIBDV_LIBS = @LIBDV_LIBS@
+LIBICONV = @LIBICONV@
+LIBIEC61883_CFLAGS = @LIBIEC61883_CFLAGS@
+LIBIEC61883_LIBS = @LIBIEC61883_LIBS@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBPNG_CFLAGS = @LIBPNG_CFLAGS@
+LIBPNG_LIBS = @LIBPNG_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBV4L2_CFLAGS = @LIBV4L2_CFLAGS@
+LIBV4L2_LIBS = @LIBV4L2_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCALEDIR = @LOCALEDIR@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJC_LDFLAGS = @OBJC_LDFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORCC = @ORCC@
+ORCC_FLAGS = @ORCC_FLAGS@
+ORC_CFLAGS = @ORC_CFLAGS@
+ORC_LIBS = @ORC_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@
+PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PLUGINDIR = @PLUGINDIR@
+POSUB = @POSUB@
+PROFILE_CFLAGS = @PROFILE_CFLAGS@
+PULSE_0_9_20_CFLAGS = @PULSE_0_9_20_CFLAGS@
+PULSE_0_9_20_LIBS = @PULSE_0_9_20_LIBS@
+PULSE_1_0_CFLAGS = @PULSE_1_0_CFLAGS@
+PULSE_1_0_LIBS = @PULSE_1_0_LIBS@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RAW1394_CFLAGS = @RAW1394_CFLAGS@
+RAW1394_LIBS = @RAW1394_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHOUT2_CFLAGS = @SHOUT2_CFLAGS@
+SHOUT2_LIBS = @SHOUT2_LIBS@
+SOUP_CFLAGS = @SOUP_CFLAGS@
+SOUP_LIBS = @SOUP_LIBS@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+TAGLIB_CFLAGS = @TAGLIB_CFLAGS@
+TAGLIB_CXXFLAGS = @TAGLIB_CXXFLAGS@
+TAGLIB_LIBS = @TAGLIB_LIBS@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VALGRIND_PATH = @VALGRIND_PATH@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
+WAVPACK_LIBS = @WAVPACK_LIBS@
+WIN32_LIBS = @WIN32_LIBS@
+XDAMAGE_CFLAGS = @XDAMAGE_CFLAGS@
+XDAMAGE_LIBS = @XDAMAGE_LIBS@
+XFIXES_CFLAGS = @XFIXES_CFLAGS@
+XFIXES_LIBS = @XFIXES_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+XMKMF = @XMKMF@
+XSHM_LIBS = @XSHM_LIBS@
+XVIDEO_LIBS = @XVIDEO_LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = libgstosxvideosink.la
+libgstosxvideosink_la_SOURCES = osxvideosink.m cocoawindow.m
+libgstosxvideosink_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \
+ $(GST_PLUGINS_BASE_CFLAGS)
+
+libgstosxvideosink_la_LIBADD = \
+ $(GST_LIBS) \
+ $(GST_BASE_LIBS) \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstvideo-$(GST_MAJORMINOR) \
+ -lgstinterfaces-$(GST_MAJORMINOR)
+
+libgstosxvideosink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -Wl,-framework -Wl,Cocoa -Wl,-framework -Wl,QuickTime -Wl,-framework -Wl,OpenGL
+libgstosxvideosink_la_LIBTOOLFLAGS = --tag=disable-static
+AM_OBJCFLAGS = $(CFLAGS) $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) -Wno-aggregate-return
+noinst_HEADERS = osxvideosink.h cocoawindow.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .lo .m .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sys/osxvideo/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu sys/osxvideo/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgstosxvideosink.la: $(libgstosxvideosink_la_OBJECTS) $(libgstosxvideosink_la_DEPENDENCIES) $(EXTRA_libgstosxvideosink_la_DEPENDENCIES)
+ $(AM_V_OBJCLD)$(libgstosxvideosink_la_LINK) -rpath $(plugindir) $(libgstosxvideosink_la_OBJECTS) $(libgstosxvideosink_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstosxvideosink_la-cocoawindow.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstosxvideosink_la-osxvideosink.Plo@am__quote@
+
+.m.o:
+@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(OBJCCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(OBJCCOMPILE) -c -o $@ $<
+
+.m.obj:
+@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(OBJCCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(OBJCCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.m.lo:
+@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LTOBJCCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LTOBJCCOMPILE) -c -o $@ $<
+
+libgstosxvideosink_la-osxvideosink.lo: osxvideosink.m
+@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(libgstosxvideosink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS) -MT libgstosxvideosink_la-osxvideosink.lo -MD -MP -MF $(DEPDIR)/libgstosxvideosink_la-osxvideosink.Tpo -c -o libgstosxvideosink_la-osxvideosink.lo `test -f 'osxvideosink.m' || echo '$(srcdir)/'`osxvideosink.m
+@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstosxvideosink_la-osxvideosink.Tpo $(DEPDIR)/libgstosxvideosink_la-osxvideosink.Plo
+@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='osxvideosink.m' object='libgstosxvideosink_la-osxvideosink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(libgstosxvideosink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS) -c -o libgstosxvideosink_la-osxvideosink.lo `test -f 'osxvideosink.m' || echo '$(srcdir)/'`osxvideosink.m
+
+libgstosxvideosink_la-cocoawindow.lo: cocoawindow.m
+@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(libgstosxvideosink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS) -MT libgstosxvideosink_la-cocoawindow.lo -MD -MP -MF $(DEPDIR)/libgstosxvideosink_la-cocoawindow.Tpo -c -o libgstosxvideosink_la-cocoawindow.lo `test -f 'cocoawindow.m' || echo '$(srcdir)/'`cocoawindow.m
+@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstosxvideosink_la-cocoawindow.Tpo $(DEPDIR)/libgstosxvideosink_la-cocoawindow.Plo
+@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='cocoawindow.m' object='libgstosxvideosink_la-cocoawindow.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(libgstosxvideosink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS) -c -o libgstosxvideosink_la-cocoawindow.lo `test -f 'cocoawindow.m' || echo '$(srcdir)/'`cocoawindow.m
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sys/osxvideo/cocoawindow.h b/sys/osxvideo/cocoawindow.h
new file mode 100644
index 0000000..7324cc7
--- /dev/null
+++ b/sys/osxvideo/cocoawindow.h
@@ -0,0 +1,74 @@
+/* GStreamer
+ * Copyright (C) 2004 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+ * Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.com>
+ *
+ * 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.
+ *
+ * The development of this code was made possible due to the involvement of Pioneers
+ * of the Inevitable, the creators of the Songbird Music player
+ *
+ */
+
+/* inspiration gained from looking at source of osx video out of xine and vlc
+ * and is reflected in the code
+ */
+
+#import <Cocoa/Cocoa.h>
+#import <QuickTime/QuickTime.h>
+#import <glib.h>
+
+struct _GstOSXImage;
+
+@interface GstGLView : NSOpenGLView
+{
+ int i_effect;
+ unsigned int pi_texture;
+ float f_x;
+ float f_y;
+ int initDone;
+ char* data;
+ int width, height;
+ BOOL fullscreen;
+ NSOpenGLContext* fullScreenContext;
+ NSOpenGLContext* actualContext;
+}
+- (void) drawQuad;
+- (void) drawRect: (NSRect) rect;
+- (id) initWithFrame: (NSRect) frame;
+- (void) initTextures;
+- (void) reloadTexture;
+- (void) cleanUp;
+- (void) displayTexture;
+- (char*) getTextureBuffer;
+- (void) setFullScreen: (BOOL) flag;
+- (void) reshape;
+- (void) setVideoSize: (int) w: (int) h;
+- (BOOL) haveSuperview;
+- (void) haveSuperviewReal: (NSMutableArray *)closure;
+- (void) addToSuperview: (NSView *)superview;
+- (void) removeFromSuperview: (id)unused;
+
+@end
+
+@interface GstOSXVideoSinkWindow: NSWindow {
+ int width, height;
+ GstGLView *gstview;
+}
+
+- (void) setContentSize: (NSSize) size;
+- (GstGLView *) gstView;
+- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag screen:(NSScreen *)aScreen;
+@end
diff --git a/sys/osxvideo/cocoawindow.m b/sys/osxvideo/cocoawindow.m
new file mode 100644
index 0000000..ed24fad
--- /dev/null
+++ b/sys/osxvideo/cocoawindow.m
@@ -0,0 +1,432 @@
+/* GStreamer
+ * Copyright (C) 2004 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+ * Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.com>
+ *
+ * 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.
+ *
+ * The development of this code was made possible due to the involvement of Pioneers
+ * of the Inevitable, the creators of the Songbird Music player
+ *
+ */
+
+/* inspiration gained from looking at source of osx video out of xine and vlc
+ * and is reflected in the code
+ */
+
+
+#include <Cocoa/Cocoa.h>
+#include <gst/gst.h>
+#import "cocoawindow.h"
+#import "osxvideosink.h"
+
+#include <OpenGL/OpenGL.h>
+#include <OpenGL/gl.h>
+#include <OpenGL/glext.h>
+
+/* Debugging category */
+#include <gst/gstinfo.h>
+
+@ implementation GstOSXVideoSinkWindow
+
+/* The object has to be released */
+- (id) initWithContentRect: (NSRect) rect
+ styleMask: (unsigned int) styleMask
+ backing: (NSBackingStoreType) bufferingType
+ defer: (BOOL) flag
+ screen:(NSScreen *) aScreen
+{
+ self = [super initWithContentRect: rect
+ styleMask: styleMask
+ backing: bufferingType
+ defer: flag
+ screen:aScreen];
+
+ GST_DEBUG ("Initializing GstOSXvideoSinkWindow");
+
+ gstview = [[GstGLView alloc] initWithFrame:rect];
+
+ if (gstview)
+ [self setContentView:gstview];
+ [self setTitle:@"GStreamer Video Output"];
+
+ return self;
+}
+
+- (void) setContentSize:(NSSize) size {
+ width = size.width;
+ height = size.height;
+
+ [gstview setVideoSize: (int) width:(int) height];
+
+ [super setContentSize:size];
+}
+
+- (GstGLView *) gstView {
+ return gstview;
+}
+
+- (void) awakeFromNib {
+ [self setAcceptsMouseMovedEvents:YES];
+}
+
+- (void) sendEvent:(NSEvent *) event {
+ BOOL taken = NO;
+
+ GST_DEBUG ("event %p type:%d", event,(gint)[event type]);
+
+ if ([event type] == NSKeyDown) {
+ }
+ /*taken = [gstview keyDown:event]; */
+
+ if (!taken) {
+ [super sendEvent:event];
+ }
+}
+
+
+@end
+
+
+//
+// OpenGL implementation
+//
+
+@ implementation GstGLView
+
+- (id) initWithFrame:(NSRect) frame {
+ NSOpenGLPixelFormat *fmt;
+ NSOpenGLPixelFormatAttribute attribs[] = {
+ NSOpenGLPFAAccelerated,
+ NSOpenGLPFANoRecovery,
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFAColorSize, 24,
+ NSOpenGLPFAAlphaSize, 8,
+ NSOpenGLPFADepthSize, 24,
+ NSOpenGLPFAWindow,
+ 0
+ };
+
+ fmt = [[NSOpenGLPixelFormat alloc]
+ initWithAttributes:attribs];
+
+ if (!fmt) {
+ GST_WARNING ("Cannot create NSOpenGLPixelFormat");
+ return nil;
+ }
+
+ self = [super initWithFrame: frame pixelFormat:fmt];
+ [fmt release];
+
+ actualContext = [self openGLContext];
+ [actualContext makeCurrentContext];
+ [actualContext update];
+
+ /* Black background */
+ glClearColor (0.0, 0.0, 0.0, 0.0);
+
+ pi_texture = 0;
+ data = nil;
+ width = frame.size.width;
+ height = frame.size.height;
+
+ GST_LOG ("Width: %d Height: %d", width, height);
+
+ [self initTextures];
+ return self;
+}
+
+- (void) reshape {
+ NSRect bounds;
+
+ GST_LOG ("reshaping");
+
+ if (!initDone) {
+ return;
+ }
+
+ [actualContext makeCurrentContext];
+
+ bounds = [self bounds];
+
+ glViewport (0, 0, (GLint) bounds.size.width, (GLint) bounds.size.height);
+
+}
+
+- (void) initTextures {
+
+ [actualContext makeCurrentContext];
+
+ /* Free previous texture if any */
+ if (pi_texture) {
+ glDeleteTextures (1, (GLuint *)&pi_texture);
+ }
+
+ if (data) {
+ data = g_realloc (data, width * height * sizeof(short)); // short or 3byte?
+ } else {
+ data = g_malloc0(width * height * sizeof(short));
+ }
+ /* Create textures */
+ glGenTextures (1, (GLuint *)&pi_texture);
+
+ glEnable (GL_TEXTURE_RECTANGLE_EXT);
+ glEnable (GL_UNPACK_CLIENT_STORAGE_APPLE);
+
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+ glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
+
+ glBindTexture (GL_TEXTURE_RECTANGLE_EXT, pi_texture);
+
+ /* Use VRAM texturing */
+ glTexParameteri (GL_TEXTURE_RECTANGLE_EXT,
+ GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE);
+
+ /* Tell the driver not to make a copy of the texture but to use
+ our buffer */
+ glPixelStorei (GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
+
+ /* Linear interpolation */
+ glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ /* I have no idea what this exactly does, but it seems to be
+ necessary for scaling */
+ glTexParameteri (GL_TEXTURE_RECTANGLE_EXT,
+ GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri (GL_TEXTURE_RECTANGLE_EXT,
+ GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ // glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); WHY ??
+
+ glTexImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA,
+ width, height, 0,
+ GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, data);
+
+
+ initDone = 1;
+}
+
+- (void) reloadTexture {
+ if (!initDone) {
+ return;
+ }
+
+ GST_LOG ("Reloading Texture");
+
+ [actualContext makeCurrentContext];
+
+ glBindTexture (GL_TEXTURE_RECTANGLE_EXT, pi_texture);
+ glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
+
+ /* glTexSubImage2D is faster than glTexImage2D
+ http://developer.apple.com/samplecode/Sample_Code/Graphics_3D/
+ TextureRange/MainOpenGLView.m.htm */
+ glTexSubImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0,
+ width, height,
+ GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, data); //FIXME
+}
+
+- (void) cleanUp {
+ initDone = 0;
+}
+
+- (void) drawQuad {
+ f_x = 1.0;
+ f_y = 1.0;
+
+ glBegin (GL_QUADS);
+ /* Top left */
+ glTexCoord2f (0.0, 0.0);
+ glVertex2f (-f_x, f_y);
+ /* Bottom left */
+ glTexCoord2f (0.0, (float) height);
+ glVertex2f (-f_x, -f_y);
+ /* Bottom right */
+ glTexCoord2f ((float) width, (float) height);
+ glVertex2f (f_x, -f_y);
+ /* Top right */
+ glTexCoord2f ((float) width, 0.0);
+ glVertex2f (f_x, f_y);
+ glEnd ();
+}
+
+- (void) drawRect:(NSRect) rect {
+ GLint params[] = { 1 };
+
+ [actualContext makeCurrentContext];
+
+ CGLSetParameter (CGLGetCurrentContext (), kCGLCPSwapInterval, params);
+
+ /* Black background */
+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if (!initDone) {
+ [actualContext flushBuffer];
+ return;
+ }
+
+ /* Draw */
+ glBindTexture (GL_TEXTURE_RECTANGLE_EXT, pi_texture); // FIXME
+ [self drawQuad];
+ /* Draw */
+ [actualContext flushBuffer];
+}
+
+- (void) displayTexture {
+ if ([self lockFocusIfCanDraw]) {
+
+ [self drawRect:[self bounds]];
+ [self reloadTexture];
+
+ [self unlockFocus];
+
+ }
+
+}
+
+- (char *) getTextureBuffer {
+ return data;
+}
+
+- (void) setFullScreen:(BOOL) flag {
+ if (!fullscreen && flag) {
+ // go to full screen
+ /* Create the new pixel format */
+ NSOpenGLPixelFormat *fmt;
+ NSOpenGLPixelFormatAttribute attribs[] = {
+ NSOpenGLPFAAccelerated,
+ NSOpenGLPFANoRecovery,
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFAColorSize, 24,
+ NSOpenGLPFAAlphaSize, 8,
+ NSOpenGLPFADepthSize, 24,
+ NSOpenGLPFAFullScreen,
+ NSOpenGLPFAScreenMask,
+ CGDisplayIDToOpenGLDisplayMask (kCGDirectMainDisplay),
+ 0
+ };
+
+ fmt = [[NSOpenGLPixelFormat alloc]
+ initWithAttributes:attribs];
+
+ if (!fmt) {
+ GST_WARNING ("Cannot create NSOpenGLPixelFormat");
+ return;
+ }
+
+ /* Create the new OpenGL context */
+ fullScreenContext = [[NSOpenGLContext alloc]
+ initWithFormat: fmt shareContext:nil];
+ if (!fullScreenContext) {
+ GST_WARNING ("Failed to create new NSOpenGLContext");
+ return;
+ }
+
+ actualContext = fullScreenContext;
+
+ /* Capture display, switch to fullscreen */
+ if (CGCaptureAllDisplays () != CGDisplayNoErr) {
+ GST_WARNING ("CGCaptureAllDisplays() failed");
+ return;
+ }
+ [fullScreenContext setFullScreen];
+ [fullScreenContext makeCurrentContext];
+
+ fullscreen = YES;
+
+ [self initTextures];
+ [self setNeedsDisplay:YES];
+
+ } else if (fullscreen && !flag) {
+ // fullscreen now and needs to go back to normal
+ initDone = NO;
+
+ actualContext = [self openGLContext];
+
+ [NSOpenGLContext clearCurrentContext];
+ [fullScreenContext clearDrawable];
+ [fullScreenContext release];
+ fullScreenContext = nil;
+
+ CGReleaseAllDisplays ();
+
+ [self reshape];
+ [self initTextures];
+
+ [self setNeedsDisplay:YES];
+
+ fullscreen = NO;
+ initDone = YES;
+ }
+}
+
+- (void) setVideoSize: (int) w:(int) h {
+ GST_LOG ("width:%d, height:%d", w, h);
+
+ width = w;
+ height = h;
+
+// if (data) g_free(data);
+
+// data = g_malloc0 (2 * w * h);
+ [self initTextures];
+}
+
+- (void) haveSuperviewReal:(NSMutableArray *)closure {
+ BOOL haveSuperview = [self superview] != nil;
+ [closure addObject:[NSNumber numberWithBool:haveSuperview]];
+}
+
+- (BOOL) haveSuperview {
+ NSMutableArray *closure = [NSMutableArray arrayWithCapacity:1];
+ [self performSelectorOnMainThread:@selector(haveSuperviewReal:)
+ withObject:(id)closure waitUntilDone:YES];
+
+ return [[closure objectAtIndex:0] boolValue];
+}
+
+- (void) addToSuperviewReal:(NSView *)superview {
+ NSRect bounds;
+ [superview addSubview:self];
+ bounds = [superview bounds];
+ [self setFrame:bounds];
+ [self setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
+}
+
+- (void) addToSuperview: (NSView *)superview {
+ [self performSelectorOnMainThread:@selector(addToSuperviewReal:)
+ withObject:superview waitUntilDone:YES];
+}
+
+- (void) removeFromSuperview: (id)unused
+{
+ [self removeFromSuperview];
+}
+
+- (void) dealloc {
+ GST_LOG ("dealloc called");
+ if (data) g_free(data);
+
+ if (fullScreenContext) {
+ [NSOpenGLContext clearCurrentContext];
+ [fullScreenContext clearDrawable];
+ [fullScreenContext release];
+ if (actualContext == fullScreenContext) actualContext = nil;
+ fullScreenContext = nil;
+ }
+
+ [super dealloc];
+}
+@end
diff --git a/sys/osxvideo/osxvideosink.h b/sys/osxvideo/osxvideosink.h
new file mode 100644
index 0000000..2a228d0
--- /dev/null
+++ b/sys/osxvideo/osxvideosink.h
@@ -0,0 +1,85 @@
+/* GStreamer
+ * Copyright (C) 2004-6 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+ * Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.com>
+ *
+ *
+ * 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.
+ *
+ *
+ * The development of this code was made possible due to the involvement of Pioneers
+ * of the Inevitable, the creators of the Songbird Music player
+ *
+ */
+
+#ifndef __GST_OSX_VIDEO_SINK_H__
+#define __GST_OSX_VIDEO_SINK_H__
+
+#include <gst/video/gstvideosink.h>
+
+#include <string.h>
+#include <math.h>
+#include <Cocoa/Cocoa.h>
+
+#include <QuickTime/QuickTime.h>
+#import "cocoawindow.h"
+
+GST_DEBUG_CATEGORY_EXTERN (gst_debug_osx_video_sink);
+#define GST_CAT_DEFAULT gst_debug_osx_video_sink
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSX_VIDEO_SINK \
+ (gst_osx_video_sink_get_type())
+#define GST_OSX_VIDEO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_OSX_VIDEO_SINK, GstOSXVideoSink))
+#define GST_OSX_VIDEO_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_OSX_VIDEO_SINK, GstOSXVideoSinkClass))
+#define GST_IS_OSX_VIDEO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OSX_VIDEO_SINK))
+#define GST_IS_OSX_VIDEO_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_OSX_VIDEO_SINK))
+
+typedef struct _GstOSXWindow GstOSXWindow;
+
+typedef struct _GstOSXVideoSink GstOSXVideoSink;
+typedef struct _GstOSXVideoSinkClass GstOSXVideoSinkClass;
+
+#define GST_TYPE_OSXVIDEOBUFFER (gst_osxvideobuffer_get_type())
+
+/* OSXWindow stuff */
+struct _GstOSXWindow {
+ gint width, height;
+ gboolean internal;
+ GstGLView* gstview;
+};
+
+struct _GstOSXVideoSink {
+ /* Our element stuff */
+ GstVideoSink videosink;
+ GstOSXWindow *osxwindow;
+ NSView *superview;
+};
+
+struct _GstOSXVideoSinkClass {
+ GstVideoSinkClass parent_class;
+};
+
+GType gst_osx_video_sink_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_OSX_VIDEO_SINK_H__ */
+
diff --git a/sys/osxvideo/osxvideosink.m b/sys/osxvideo/osxvideosink.m
new file mode 100644
index 0000000..5914550
--- /dev/null
+++ b/sys/osxvideo/osxvideosink.m
@@ -0,0 +1,524 @@
+/* GStreamer
+ * OSX video sink
+ * Copyright (C) 2004-6 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+ * Copyright (C) 2007,2008,2009 Pioneers of the Inevitable <songbird@songbirdnest.com>
+ *
+ * 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.
+ *
+ * The development of this code was made possible due to the involvement of
+ * Pioneers of the Inevitable, the creators of the Songbird Music player.
+ *
+ */
+
+/**
+ * SECTION:element-osxvideosink
+ *
+ * The OSXVideoSink renders video frames to a MacOSX window. The video output
+ * must be directed to a window embedded in an existing NSApp.
+ *
+ * When the NSView to be embedded is created an element #GstMessage with a
+ * name of 'have-ns-view' will be created and posted on the bus.
+ * The pointer to the NSView to embed will be in the 'nsview' field of that
+ * message. The application MUST handle this message and embed the view
+ * appropriately.
+ */
+
+#include "config.h"
+#include <gst/interfaces/xoverlay.h>
+
+#include "osxvideosink.h"
+#include <unistd.h>
+#import "cocoawindow.h"
+
+GST_DEBUG_CATEGORY (gst_debug_osx_video_sink);
+#define GST_CAT_DEFAULT gst_debug_osx_video_sink
+
+static GstStaticPadTemplate gst_osx_video_sink_sink_template_factory =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-raw-yuv, "
+ "framerate = (fraction) [ 0, MAX ], "
+ "width = (int) [ 1, MAX ], "
+ "height = (int) [ 1, MAX ], "
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+ "format = (fourcc) YUY2")
+#else
+ "format = (fourcc) UYVY")
+#endif
+ );
+
+enum
+{
+ ARG_0,
+ ARG_EMBED,
+};
+
+static void gst_osx_video_sink_osxwindow_destroy (GstOSXVideoSink * osxvideosink);
+
+static GstVideoSinkClass *parent_class = NULL;
+
+/* This function handles osx window creation */
+static gboolean
+gst_osx_video_sink_osxwindow_create (GstOSXVideoSink * osxvideosink, gint width,
+ gint height)
+{
+ NSRect rect;
+ GstOSXWindow *osxwindow = NULL;
+ GstStructure *s;
+ GstMessage *msg;
+ gboolean res = TRUE;
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ g_return_val_if_fail (GST_IS_OSX_VIDEO_SINK (osxvideosink), FALSE);
+
+ GST_DEBUG_OBJECT (osxvideosink, "Creating new OSX window");
+
+ osxvideosink->osxwindow = osxwindow = g_new0 (GstOSXWindow, 1);
+
+ osxwindow->width = width;
+ osxwindow->height = height;
+
+ /* Allocate our GstGLView for the window, and then tell the application
+ * about it (hopefully it's listening...) */
+ rect.origin.x = 0.0;
+ rect.origin.y = 0.0;
+ rect.size.width = (float) osxwindow->width;
+ rect.size.height = (float) osxwindow->height;
+ osxwindow->gstview =[[GstGLView alloc] initWithFrame:rect];
+
+ s = gst_structure_new ("have-ns-view",
+ "nsview", G_TYPE_POINTER, osxwindow->gstview,
+ nil);
+
+ msg = gst_message_new_element (GST_OBJECT (osxvideosink), s);
+ gst_element_post_message (GST_ELEMENT (osxvideosink), msg);
+
+ GST_INFO_OBJECT (osxvideosink, "'have-ns-view' message sent");
+
+ /* check if have-ns-view was handled and osxwindow->gstview was added to a
+ * superview
+ */
+ if ([osxwindow->gstview haveSuperview] == NO) {
+ /* have-ns-view wasn't handled, post prepare-xwindow-id */
+ if (osxvideosink->superview == NULL) {
+ GST_INFO_OBJECT (osxvideosink, "emitting prepare-xwindow-id");
+ gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (osxvideosink));
+ }
+
+ if (osxvideosink->superview != NULL) {
+ /* prepare-xwindow-id was handled, we have the superview in
+ * osxvideosink->superview. We now add osxwindow->gstview to the superview
+ * from the main thread
+ */
+ GST_INFO_OBJECT (osxvideosink, "we have a superview, adding our view to it");
+ [osxwindow->gstview performSelectorOnMainThread:@selector(addToSuperview:)
+ withObject:osxvideosink->superview waitUntilDone:YES];
+ } else {
+ /* the view wasn't added to a superview. It's possible that the
+ * application handled have-ns-view, stored our view internally and is
+ * going to add it to a superview later (webkit does that now).
+ */
+ GST_INFO_OBJECT (osxvideosink, "no superview");
+ }
+ }
+
+ [pool release];
+
+ return res;
+}
+
+static void
+gst_osx_video_sink_osxwindow_destroy (GstOSXVideoSink * osxvideosink)
+{
+ NSAutoreleasePool *pool;
+
+ g_return_if_fail (GST_IS_OSX_VIDEO_SINK (osxvideosink));
+ pool = [[NSAutoreleasePool alloc] init];
+
+ if (osxvideosink->osxwindow) {
+ if (osxvideosink->superview) {
+ [osxvideosink->osxwindow->gstview
+ performSelectorOnMainThread:@selector(removeFromSuperview:)
+ withObject:(id)nil waitUntilDone:YES];
+ }
+ [osxvideosink->osxwindow->gstview release];
+
+ g_free (osxvideosink->osxwindow);
+ osxvideosink->osxwindow = NULL;
+ }
+ [pool release];
+}
+
+/* This function resizes a GstXWindow */
+static void
+gst_osx_video_sink_osxwindow_resize (GstOSXVideoSink * osxvideosink,
+ GstOSXWindow * osxwindow, guint width, guint height)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ g_return_if_fail (osxwindow != NULL);
+ g_return_if_fail (GST_IS_OSX_VIDEO_SINK (osxvideosink));
+
+ osxwindow->width = width;
+ osxwindow->height = height;
+
+ GST_DEBUG_OBJECT (osxvideosink, "Resizing window to (%d,%d)", width, height);
+
+ /* Directly resize the underlying view */
+ GST_DEBUG_OBJECT (osxvideosink, "Calling setVideoSize on %p", osxwindow->gstview);
+ [osxwindow->gstview setVideoSize:width :height];
+
+ [pool release];
+}
+
+static gboolean
+gst_osx_video_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
+{
+ GstOSXVideoSink *osxvideosink;
+ GstStructure *structure;
+ gboolean res, result = FALSE;
+ gint video_width, video_height;
+
+ osxvideosink = GST_OSX_VIDEO_SINK (bsink);
+
+ GST_DEBUG_OBJECT (osxvideosink, "caps: %" GST_PTR_FORMAT, caps);
+
+ structure = gst_caps_get_structure (caps, 0);
+ res = gst_structure_get_int (structure, "width", &video_width);
+ res &= gst_structure_get_int (structure, "height", &video_height);
+
+ if (!res) {
+ goto beach;
+ }
+
+ GST_DEBUG_OBJECT (osxvideosink, "our format is: %dx%d video",
+ video_width, video_height);
+
+ GST_VIDEO_SINK_WIDTH (osxvideosink) = video_width;
+ GST_VIDEO_SINK_HEIGHT (osxvideosink) = video_height;
+
+ gst_osx_video_sink_osxwindow_resize (osxvideosink, osxvideosink->osxwindow,
+ video_width, video_height);
+ result = TRUE;
+
+beach:
+ return result;
+
+}
+
+static GstStateChangeReturn
+gst_osx_video_sink_change_state (GstElement * element,
+ GstStateChange transition)
+{
+ GstOSXVideoSink *osxvideosink;
+ GstStateChangeReturn ret;
+
+ osxvideosink = GST_OSX_VIDEO_SINK (element);
+
+ GST_DEBUG_OBJECT (osxvideosink, "%s => %s",
+ gst_element_state_get_name(GST_STATE_TRANSITION_CURRENT (transition)),
+ gst_element_state_get_name(GST_STATE_TRANSITION_NEXT (transition)));
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ /* Creating our window and our image */
+ GST_VIDEO_SINK_WIDTH (osxvideosink) = 320;
+ GST_VIDEO_SINK_HEIGHT (osxvideosink) = 240;
+ if (!gst_osx_video_sink_osxwindow_create (osxvideosink,
+ GST_VIDEO_SINK_WIDTH (osxvideosink),
+ GST_VIDEO_SINK_HEIGHT (osxvideosink))) {
+ ret = GST_STATE_CHANGE_FAILURE;
+ goto done;
+ }
+ break;
+ default:
+ break;
+ }
+
+ ret = (GST_ELEMENT_CLASS (parent_class))->change_state (element, transition);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ GST_VIDEO_SINK_WIDTH (osxvideosink) = 0;
+ GST_VIDEO_SINK_HEIGHT (osxvideosink) = 0;
+ gst_osx_video_sink_osxwindow_destroy (osxvideosink);
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+done:
+ return ret;
+}
+
+static GstFlowReturn
+gst_osx_video_sink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
+{
+ GstOSXVideoSink *osxvideosink;
+ guint8 *viewdata;
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ osxvideosink = GST_OSX_VIDEO_SINK (bsink);
+ viewdata = (guint8 *) [osxvideosink->osxwindow->gstview getTextureBuffer];
+
+ GST_DEBUG ("show_frame");
+ memcpy (viewdata, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ [osxvideosink->osxwindow->gstview displayTexture];
+
+ [pool release];
+
+ return GST_FLOW_OK;
+}
+
+/* Buffer management */
+
+
+
+/* =========================================== */
+/* */
+/* Init & Class init */
+/* */
+/* =========================================== */
+
+static void
+gst_osx_video_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOSXVideoSink *osxvideosink;
+
+ g_return_if_fail (GST_IS_OSX_VIDEO_SINK (object));
+
+ osxvideosink = GST_OSX_VIDEO_SINK (object);
+
+ switch (prop_id) {
+ case ARG_EMBED:
+ /* Ignore, just here for backwards compatibility */
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_osx_video_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstOSXVideoSink *osxvideosink;
+
+ g_return_if_fail (GST_IS_OSX_VIDEO_SINK (object));
+
+ osxvideosink = GST_OSX_VIDEO_SINK (object);
+
+ switch (prop_id) {
+ case ARG_EMBED:
+ g_value_set_boolean (value, TRUE);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+gst_osx_video_sink_init (GstOSXVideoSink * osxvideosink)
+{
+ osxvideosink->osxwindow = NULL;
+ osxvideosink->superview = NULL;
+}
+
+static void
+gst_osx_video_sink_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_set_details_simple (element_class, "OSX Video sink",
+ "Sink/Video", "OSX native videosink",
+ "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
+
+ gst_element_class_add_static_pad_template (element_class,
+ &gst_osx_video_sink_sink_template_factory);
+}
+
+static void
+gst_osx_video_sink_finalize (GObject *object)
+{
+ GstOSXVideoSink *osxvideosink = GST_OSX_VIDEO_SINK (object);
+
+ if (osxvideosink->superview)
+ [osxvideosink->superview release];
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_osx_video_sink_class_init (GstOSXVideoSinkClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSinkClass *gstbasesink_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesink_class = (GstBaseSinkClass *) klass;
+
+
+ parent_class = g_type_class_ref (GST_TYPE_VIDEO_SINK);
+
+ gobject_class->set_property = gst_osx_video_sink_set_property;
+ gobject_class->get_property = gst_osx_video_sink_get_property;
+ gobject_class->finalize = gst_osx_video_sink_finalize;
+
+ gstbasesink_class->set_caps = gst_osx_video_sink_setcaps;
+ gstbasesink_class->preroll = gst_osx_video_sink_show_frame;
+ gstbasesink_class->render = gst_osx_video_sink_show_frame;
+ gstelement_class->change_state = gst_osx_video_sink_change_state;
+
+ /**
+ * GstOSXVideoSink:embed
+ *
+ * Set to #TRUE if you are embedding the video window in an application.
+ *
+ **/
+
+ g_object_class_install_property (gobject_class, ARG_EMBED,
+ g_param_spec_boolean ("embed", "embed", "For ABI compatiblity only, do not use",
+ FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static gboolean
+gst_osx_video_sink_interface_supported (GstImplementsInterface * iface, GType type)
+{
+ g_assert (type == GST_TYPE_X_OVERLAY);
+ return TRUE;
+}
+
+static void
+gst_osx_video_sink_interface_init (GstImplementsInterfaceClass * klass)
+{
+ klass->supported = gst_osx_video_sink_interface_supported;
+}
+
+static void
+gst_osx_video_sink_set_window_handle (GstXOverlay * overlay, guintptr handle_id)
+{
+ GstOSXVideoSink *osxvideosink = GST_OSX_VIDEO_SINK (overlay);
+ gulong window_id = (gulong) handle_id;
+
+ if (osxvideosink->superview) {
+ GST_INFO_OBJECT (osxvideosink, "old xwindow id %p", osxvideosink->superview);
+ if (osxvideosink->osxwindow) {
+ [osxvideosink->osxwindow->gstview
+ performSelectorOnMainThread:@selector(removeFromSuperview:)
+ withObject:(id)nil waitUntilDone:YES];
+ }
+ [osxvideosink->superview release];
+ }
+
+ GST_INFO_OBJECT (osxvideosink, "set xwindow id 0x%lx", window_id);
+ osxvideosink->superview = [((NSView *) window_id) retain];
+ if (osxvideosink->osxwindow) {
+ [osxvideosink->osxwindow->gstview performSelectorOnMainThread:@selector(addToSuperview:)
+ withObject:osxvideosink->superview waitUntilDone:YES];
+ }
+}
+
+static void
+gst_osx_video_sink_xoverlay_init (GstXOverlayClass * iface)
+{
+ iface->set_window_handle = gst_osx_video_sink_set_window_handle;
+ iface->expose = NULL;
+ iface->handle_events = NULL;
+}
+
+/* ============================================================= */
+/* */
+/* Public Methods */
+/* */
+/* ============================================================= */
+
+/* =========================================== */
+/* */
+/* Object typing & Creation */
+/* */
+/* =========================================== */
+
+GType
+gst_osx_video_sink_get_type (void)
+{
+ static GType osxvideosink_type = 0;
+
+ if (!osxvideosink_type) {
+ static const GTypeInfo osxvideosink_info = {
+ sizeof (GstOSXVideoSinkClass),
+ gst_osx_video_sink_base_init,
+ NULL,
+ (GClassInitFunc) gst_osx_video_sink_class_init,
+ NULL,
+ NULL,
+ sizeof (GstOSXVideoSink),
+ 0,
+ (GInstanceInitFunc) gst_osx_video_sink_init,
+ };
+
+ static const GInterfaceInfo iface_info = {
+ (GInterfaceInitFunc) gst_osx_video_sink_interface_init,
+ NULL,
+ NULL,
+ };
+
+ static const GInterfaceInfo overlay_info = {
+ (GInterfaceInitFunc) gst_osx_video_sink_xoverlay_init,
+ NULL,
+ NULL,
+ };
+
+ osxvideosink_type = g_type_register_static (GST_TYPE_VIDEO_SINK,
+ "GstOSXVideoSink", &osxvideosink_info, 0);
+
+ g_type_add_interface_static (osxvideosink_type,
+ GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
+ g_type_add_interface_static (osxvideosink_type, GST_TYPE_X_OVERLAY,
+ &overlay_info);
+ }
+
+ return osxvideosink_type;
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+
+ if (!gst_element_register (plugin, "osxvideosink",
+ GST_RANK_PRIMARY, GST_TYPE_OSX_VIDEO_SINK))
+ return FALSE;
+
+ GST_DEBUG_CATEGORY_INIT (gst_debug_osx_video_sink, "osxvideosink", 0,
+ "osxvideosink element");
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "osxvideo",
+ "OSX native video output plugin",
+ plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/sunaudio/Makefile.am b/sys/sunaudio/Makefile.am
new file mode 100644
index 0000000..e106ce3
--- /dev/null
+++ b/sys/sunaudio/Makefile.am
@@ -0,0 +1,26 @@
+plugin_LTLIBRARIES = libgstsunaudio.la
+
+libgstsunaudio_la_SOURCES = gstsunaudio.c \
+ gstsunaudiosink.c \
+ gstsunaudiomixerctrl.c \
+ gstsunaudiomixer.c \
+ gstsunaudiomixertrack.c \
+ gstsunaudiomixeroptions.c \
+ gstsunaudiosrc.c
+
+libgstsunaudio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
+libgstsunaudio_la_LIBADD = \
+ -lgstinterfaces-@GST_MAJORMINOR@ \
+ -lgstaudio-@GST_MAJORMINOR@ \
+ $(GST_PLUGINS_BASE_LIBS) \
+ $(GST_LIBS)
+libgstsunaudio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstsunaudio_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = gstsunaudiosink.h \
+ gstsunaudiomixer.h \
+ gstsunaudiomixerctrl.h \
+ gstsunaudiomixertrack.h \
+ gstsunaudiomixeroptions.h \
+ gstsunaudiosrc.h
+
diff --git a/sys/sunaudio/Makefile.in b/sys/sunaudio/Makefile.in
new file mode 100644
index 0000000..a1d1abd
--- /dev/null
+++ b/sys/sunaudio/Makefile.in
@@ -0,0 +1,877 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sys/sunaudio
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
+ $(top_srcdir)/common/m4/as-auto-alt.m4 \
+ $(top_srcdir)/common/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/common/m4/as-gcc-inline-assembly.m4 \
+ $(top_srcdir)/common/m4/as-objc.m4 \
+ $(top_srcdir)/common/m4/as-python.m4 \
+ $(top_srcdir)/common/m4/as-scrub-include.m4 \
+ $(top_srcdir)/common/m4/as-version.m4 \
+ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
+ $(top_srcdir)/common/m4/gst-arch.m4 \
+ $(top_srcdir)/common/m4/gst-args.m4 \
+ $(top_srcdir)/common/m4/gst-check.m4 \
+ $(top_srcdir)/common/m4/gst-default.m4 \
+ $(top_srcdir)/common/m4/gst-dowhile.m4 \
+ $(top_srcdir)/common/m4/gst-error.m4 \
+ $(top_srcdir)/common/m4/gst-feature.m4 \
+ $(top_srcdir)/common/m4/gst-gettext.m4 \
+ $(top_srcdir)/common/m4/gst-glib2.m4 \
+ $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \
+ $(top_srcdir)/common/m4/gst-platform.m4 \
+ $(top_srcdir)/common/m4/gst-plugin-docs.m4 \
+ $(top_srcdir)/common/m4/gst-plugindir.m4 \
+ $(top_srcdir)/common/m4/gst-x11.m4 \
+ $(top_srcdir)/common/m4/gst.m4 \
+ $(top_srcdir)/common/m4/gtk-doc.m4 \
+ $(top_srcdir)/common/m4/orc.m4 $(top_srcdir)/common/m4/pkg.m4 \
+ $(top_srcdir)/m4/aalib.m4 $(top_srcdir)/m4/esd.m4 \
+ $(top_srcdir)/m4/gconf-2.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gst-fionread.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgstsunaudio_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_libgstsunaudio_la_OBJECTS = libgstsunaudio_la-gstsunaudio.lo \
+ libgstsunaudio_la-gstsunaudiosink.lo \
+ libgstsunaudio_la-gstsunaudiomixerctrl.lo \
+ libgstsunaudio_la-gstsunaudiomixer.lo \
+ libgstsunaudio_la-gstsunaudiomixertrack.lo \
+ libgstsunaudio_la-gstsunaudiomixeroptions.lo \
+ libgstsunaudio_la-gstsunaudiosrc.lo
+libgstsunaudio_la_OBJECTS = $(am_libgstsunaudio_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libgstsunaudio_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
+ $(CCLD) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) \
+ $(libgstsunaudio_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libgstsunaudio_la_SOURCES)
+DIST_SOURCES = $(libgstsunaudio_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+AALIB_CFLAGS = @AALIB_CFLAGS@
+AALIB_CONFIG = @AALIB_CONFIG@
+AALIB_LIBS = @AALIB_LIBS@
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+ANNODEX_CFLAGS = @ANNODEX_CFLAGS@
+ANNODEX_LIBS = @ANNODEX_LIBS@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BZ2_LIBS = @BZ2_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_GOBJECT_CFLAGS = @CAIRO_GOBJECT_CFLAGS@
+CAIRO_GOBJECT_LIBS = @CAIRO_GOBJECT_LIBS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@
+DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@
+DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@
+DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@
+DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@
+DIRECTSOUND_CFLAGS = @DIRECTSOUND_CFLAGS@
+DIRECTSOUND_LDFLAGS = @DIRECTSOUND_LDFLAGS@
+DIRECTSOUND_LIBS = @DIRECTSOUND_LIBS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DV1394_CFLAGS = @DV1394_CFLAGS@
+DV1394_LIBS = @DV1394_LIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ERROR_CFLAGS = @ERROR_CFLAGS@
+ERROR_CXXFLAGS = @ERROR_CXXFLAGS@
+ESD_CFLAGS = @ESD_CFLAGS@
+ESD_CONFIG = @ESD_CONFIG@
+ESD_LIBS = @ESD_LIBS@
+EXEEXT = @EXEEXT@
+FFLAGS = @FFLAGS@
+FGREP = @FGREP@
+FLAC_CFLAGS = @FLAC_CFLAGS@
+FLAC_LIBS = @FLAC_LIBS@
+GCONFTOOL = @GCONFTOOL@
+GCONF_CFLAGS = @GCONF_CFLAGS@
+GCONF_LIBS = @GCONF_LIBS@
+GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+GCOV = @GCOV@
+GCOV_CFLAGS = @GCOV_CFLAGS@
+GCOV_LIBS = @GCOV_LIBS@
+GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@
+GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_PREFIX = @GLIB_PREFIX@
+GLIB_REQ = @GLIB_REQ@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@
+GSTPB_PREFIX = @GSTPB_PREFIX@
+GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@
+GST_BASE_CFLAGS = @GST_BASE_CFLAGS@
+GST_BASE_LIBS = @GST_BASE_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_CONTROLLER_CFLAGS = @GST_CONTROLLER_CFLAGS@
+GST_CONTROLLER_LIBS = @GST_CONTROLLER_LIBS@
+GST_CXXFLAGS = @GST_CXXFLAGS@
+GST_GDP_CFLAGS = @GST_GDP_CFLAGS@
+GST_GDP_LIBS = @GST_GDP_LIBS@
+GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@
+GST_LIBS = @GST_LIBS@
+GST_LICENSE = @GST_LICENSE@
+GST_LT_LDFLAGS = @GST_LT_LDFLAGS@
+GST_MAJORMINOR = @GST_MAJORMINOR@
+GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@
+GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@
+GST_PACKAGE_NAME = @GST_PACKAGE_NAME@
+GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@
+GST_PLUGINS_ALL = @GST_PLUGINS_ALL@
+GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@
+GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@
+GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@
+GST_PLUGINS_DIR = @GST_PLUGINS_DIR@
+GST_PLUGINS_SELECTED = @GST_PLUGINS_SELECTED@
+GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@
+GST_PREFIX = @GST_PREFIX@
+GST_TOOLS_DIR = @GST_TOOLS_DIR@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_X11_CFLAGS = @GTK_X11_CFLAGS@
+GTK_X11_LIBS = @GTK_X11_LIBS@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+HAVE_AVC1394 = @HAVE_AVC1394@
+HAVE_BZ2 = @HAVE_BZ2@
+HAVE_CXX = @HAVE_CXX@
+HAVE_DIRECTSOUND = @HAVE_DIRECTSOUND@
+HAVE_GCONFTOOL = @HAVE_GCONFTOOL@
+HAVE_ROM1394 = @HAVE_ROM1394@
+HAVE_SPEEX = @HAVE_SPEEX@
+HAVE_X = @HAVE_X@
+HAVE_XSHM = @HAVE_XSHM@
+HAVE_ZLIB = @HAVE_ZLIB@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JACK_0_120_1_CFLAGS = @JACK_0_120_1_CFLAGS@
+JACK_0_120_1_LIBS = @JACK_0_120_1_LIBS@
+JACK_1_9_7_CFLAGS = @JACK_1_9_7_CFLAGS@
+JACK_1_9_7_LIBS = @JACK_1_9_7_LIBS@
+JACK_CFLAGS = @JACK_CFLAGS@
+JACK_LIBS = @JACK_LIBS@
+JPEG_LIBS = @JPEG_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCACA_CFLAGS = @LIBCACA_CFLAGS@
+LIBCACA_LIBS = @LIBCACA_LIBS@
+LIBDV_CFLAGS = @LIBDV_CFLAGS@
+LIBDV_LIBS = @LIBDV_LIBS@
+LIBICONV = @LIBICONV@
+LIBIEC61883_CFLAGS = @LIBIEC61883_CFLAGS@
+LIBIEC61883_LIBS = @LIBIEC61883_LIBS@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBPNG_CFLAGS = @LIBPNG_CFLAGS@
+LIBPNG_LIBS = @LIBPNG_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBV4L2_CFLAGS = @LIBV4L2_CFLAGS@
+LIBV4L2_LIBS = @LIBV4L2_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCALEDIR = @LOCALEDIR@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJC_LDFLAGS = @OBJC_LDFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORCC = @ORCC@
+ORCC_FLAGS = @ORCC_FLAGS@
+ORC_CFLAGS = @ORC_CFLAGS@
+ORC_LIBS = @ORC_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@
+PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PLUGINDIR = @PLUGINDIR@
+POSUB = @POSUB@
+PROFILE_CFLAGS = @PROFILE_CFLAGS@
+PULSE_0_9_20_CFLAGS = @PULSE_0_9_20_CFLAGS@
+PULSE_0_9_20_LIBS = @PULSE_0_9_20_LIBS@
+PULSE_1_0_CFLAGS = @PULSE_1_0_CFLAGS@
+PULSE_1_0_LIBS = @PULSE_1_0_LIBS@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RAW1394_CFLAGS = @RAW1394_CFLAGS@
+RAW1394_LIBS = @RAW1394_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHOUT2_CFLAGS = @SHOUT2_CFLAGS@
+SHOUT2_LIBS = @SHOUT2_LIBS@
+SOUP_CFLAGS = @SOUP_CFLAGS@
+SOUP_LIBS = @SOUP_LIBS@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+TAGLIB_CFLAGS = @TAGLIB_CFLAGS@
+TAGLIB_CXXFLAGS = @TAGLIB_CXXFLAGS@
+TAGLIB_LIBS = @TAGLIB_LIBS@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VALGRIND_PATH = @VALGRIND_PATH@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
+WAVPACK_LIBS = @WAVPACK_LIBS@
+WIN32_LIBS = @WIN32_LIBS@
+XDAMAGE_CFLAGS = @XDAMAGE_CFLAGS@
+XDAMAGE_LIBS = @XDAMAGE_LIBS@
+XFIXES_CFLAGS = @XFIXES_CFLAGS@
+XFIXES_LIBS = @XFIXES_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+XMKMF = @XMKMF@
+XSHM_LIBS = @XSHM_LIBS@
+XVIDEO_LIBS = @XVIDEO_LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = libgstsunaudio.la
+libgstsunaudio_la_SOURCES = gstsunaudio.c \
+ gstsunaudiosink.c \
+ gstsunaudiomixerctrl.c \
+ gstsunaudiomixer.c \
+ gstsunaudiomixertrack.c \
+ gstsunaudiomixeroptions.c \
+ gstsunaudiosrc.c
+
+libgstsunaudio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
+libgstsunaudio_la_LIBADD = \
+ -lgstinterfaces-@GST_MAJORMINOR@ \
+ -lgstaudio-@GST_MAJORMINOR@ \
+ $(GST_PLUGINS_BASE_LIBS) \
+ $(GST_LIBS)
+
+libgstsunaudio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstsunaudio_la_LIBTOOLFLAGS = --tag=disable-static
+noinst_HEADERS = gstsunaudiosink.h \
+ gstsunaudiomixer.h \
+ gstsunaudiomixerctrl.h \
+ gstsunaudiomixertrack.h \
+ gstsunaudiomixeroptions.h \
+ gstsunaudiosrc.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sys/sunaudio/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu sys/sunaudio/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgstsunaudio.la: $(libgstsunaudio_la_OBJECTS) $(libgstsunaudio_la_DEPENDENCIES) $(EXTRA_libgstsunaudio_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgstsunaudio_la_LINK) -rpath $(plugindir) $(libgstsunaudio_la_OBJECTS) $(libgstsunaudio_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstsunaudio_la-gstsunaudio.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstsunaudio_la-gstsunaudiomixer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstsunaudio_la-gstsunaudiomixerctrl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstsunaudio_la-gstsunaudiomixeroptions.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstsunaudio_la-gstsunaudiomixertrack.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstsunaudio_la-gstsunaudiosink.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstsunaudio_la-gstsunaudiosrc.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libgstsunaudio_la-gstsunaudio.lo: gstsunaudio.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -MT libgstsunaudio_la-gstsunaudio.lo -MD -MP -MF $(DEPDIR)/libgstsunaudio_la-gstsunaudio.Tpo -c -o libgstsunaudio_la-gstsunaudio.lo `test -f 'gstsunaudio.c' || echo '$(srcdir)/'`gstsunaudio.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstsunaudio_la-gstsunaudio.Tpo $(DEPDIR)/libgstsunaudio_la-gstsunaudio.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstsunaudio.c' object='libgstsunaudio_la-gstsunaudio.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -c -o libgstsunaudio_la-gstsunaudio.lo `test -f 'gstsunaudio.c' || echo '$(srcdir)/'`gstsunaudio.c
+
+libgstsunaudio_la-gstsunaudiosink.lo: gstsunaudiosink.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -MT libgstsunaudio_la-gstsunaudiosink.lo -MD -MP -MF $(DEPDIR)/libgstsunaudio_la-gstsunaudiosink.Tpo -c -o libgstsunaudio_la-gstsunaudiosink.lo `test -f 'gstsunaudiosink.c' || echo '$(srcdir)/'`gstsunaudiosink.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstsunaudio_la-gstsunaudiosink.Tpo $(DEPDIR)/libgstsunaudio_la-gstsunaudiosink.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstsunaudiosink.c' object='libgstsunaudio_la-gstsunaudiosink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -c -o libgstsunaudio_la-gstsunaudiosink.lo `test -f 'gstsunaudiosink.c' || echo '$(srcdir)/'`gstsunaudiosink.c
+
+libgstsunaudio_la-gstsunaudiomixerctrl.lo: gstsunaudiomixerctrl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -MT libgstsunaudio_la-gstsunaudiomixerctrl.lo -MD -MP -MF $(DEPDIR)/libgstsunaudio_la-gstsunaudiomixerctrl.Tpo -c -o libgstsunaudio_la-gstsunaudiomixerctrl.lo `test -f 'gstsunaudiomixerctrl.c' || echo '$(srcdir)/'`gstsunaudiomixerctrl.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstsunaudio_la-gstsunaudiomixerctrl.Tpo $(DEPDIR)/libgstsunaudio_la-gstsunaudiomixerctrl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstsunaudiomixerctrl.c' object='libgstsunaudio_la-gstsunaudiomixerctrl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -c -o libgstsunaudio_la-gstsunaudiomixerctrl.lo `test -f 'gstsunaudiomixerctrl.c' || echo '$(srcdir)/'`gstsunaudiomixerctrl.c
+
+libgstsunaudio_la-gstsunaudiomixer.lo: gstsunaudiomixer.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -MT libgstsunaudio_la-gstsunaudiomixer.lo -MD -MP -MF $(DEPDIR)/libgstsunaudio_la-gstsunaudiomixer.Tpo -c -o libgstsunaudio_la-gstsunaudiomixer.lo `test -f 'gstsunaudiomixer.c' || echo '$(srcdir)/'`gstsunaudiomixer.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstsunaudio_la-gstsunaudiomixer.Tpo $(DEPDIR)/libgstsunaudio_la-gstsunaudiomixer.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstsunaudiomixer.c' object='libgstsunaudio_la-gstsunaudiomixer.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -c -o libgstsunaudio_la-gstsunaudiomixer.lo `test -f 'gstsunaudiomixer.c' || echo '$(srcdir)/'`gstsunaudiomixer.c
+
+libgstsunaudio_la-gstsunaudiomixertrack.lo: gstsunaudiomixertrack.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -MT libgstsunaudio_la-gstsunaudiomixertrack.lo -MD -MP -MF $(DEPDIR)/libgstsunaudio_la-gstsunaudiomixertrack.Tpo -c -o libgstsunaudio_la-gstsunaudiomixertrack.lo `test -f 'gstsunaudiomixertrack.c' || echo '$(srcdir)/'`gstsunaudiomixertrack.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstsunaudio_la-gstsunaudiomixertrack.Tpo $(DEPDIR)/libgstsunaudio_la-gstsunaudiomixertrack.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstsunaudiomixertrack.c' object='libgstsunaudio_la-gstsunaudiomixertrack.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -c -o libgstsunaudio_la-gstsunaudiomixertrack.lo `test -f 'gstsunaudiomixertrack.c' || echo '$(srcdir)/'`gstsunaudiomixertrack.c
+
+libgstsunaudio_la-gstsunaudiomixeroptions.lo: gstsunaudiomixeroptions.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -MT libgstsunaudio_la-gstsunaudiomixeroptions.lo -MD -MP -MF $(DEPDIR)/libgstsunaudio_la-gstsunaudiomixeroptions.Tpo -c -o libgstsunaudio_la-gstsunaudiomixeroptions.lo `test -f 'gstsunaudiomixeroptions.c' || echo '$(srcdir)/'`gstsunaudiomixeroptions.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstsunaudio_la-gstsunaudiomixeroptions.Tpo $(DEPDIR)/libgstsunaudio_la-gstsunaudiomixeroptions.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstsunaudiomixeroptions.c' object='libgstsunaudio_la-gstsunaudiomixeroptions.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -c -o libgstsunaudio_la-gstsunaudiomixeroptions.lo `test -f 'gstsunaudiomixeroptions.c' || echo '$(srcdir)/'`gstsunaudiomixeroptions.c
+
+libgstsunaudio_la-gstsunaudiosrc.lo: gstsunaudiosrc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -MT libgstsunaudio_la-gstsunaudiosrc.lo -MD -MP -MF $(DEPDIR)/libgstsunaudio_la-gstsunaudiosrc.Tpo -c -o libgstsunaudio_la-gstsunaudiosrc.lo `test -f 'gstsunaudiosrc.c' || echo '$(srcdir)/'`gstsunaudiosrc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstsunaudio_la-gstsunaudiosrc.Tpo $(DEPDIR)/libgstsunaudio_la-gstsunaudiosrc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstsunaudiosrc.c' object='libgstsunaudio_la-gstsunaudiosrc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstsunaudio_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstsunaudio_la_CFLAGS) $(CFLAGS) -c -o libgstsunaudio_la-gstsunaudiosrc.lo `test -f 'gstsunaudiosrc.c' || echo '$(srcdir)/'`gstsunaudiosrc.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sys/sunaudio/gstsunaudio.c b/sys/sunaudio/gstsunaudio.c
new file mode 100644
index 0000000..07aa575
--- /dev/null
+++ b/sys/sunaudio/gstsunaudio.c
@@ -0,0 +1,63 @@
+/*
+ * GStreamer - SunAudio plugin
+ * Copyright (C) 2005,2006 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ *
+ * 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 "gst/gst-i18n-plugin.h"
+
+#include "gstsunaudiomixer.h"
+#include "gstsunaudiosink.h"
+#include "gstsunaudiosrc.h"
+
+extern gchar *__gst_oss_plugin_dir;
+
+GST_DEBUG_CATEGORY (sunaudio_debug);
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ if (!gst_element_register (plugin, "sunaudiomixer", GST_RANK_NONE,
+ GST_TYPE_SUNAUDIO_MIXER) ||
+ !gst_element_register (plugin, "sunaudiosink", GST_RANK_SECONDARY,
+ GST_TYPE_SUNAUDIO_SINK) ||
+ !gst_element_register (plugin, "sunaudiosrc", GST_RANK_SECONDARY,
+ GST_TYPE_SUNAUDIO_SRC)) {
+ return FALSE;
+ }
+
+ GST_DEBUG_CATEGORY_INIT (sunaudio_debug, "sunaudio", 0, "sunaudio elements");
+
+#ifdef ENABLE_NLS
+ setlocale (LC_ALL, "");
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+#endif /* ENABLE_NLS */
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "sunaudio",
+ "Sun Audio support for GStreamer",
+ plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/sunaudio/gstsunaudiomixer.c b/sys/sunaudio/gstsunaudiomixer.c
new file mode 100644
index 0000000..7688450
--- /dev/null
+++ b/sys/sunaudio/gstsunaudiomixer.c
@@ -0,0 +1,104 @@
+/*
+ * GStreamer - SunAudio mixer
+ * Copyright (C) 2005,2006 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ *
+ * 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-sunaudiomixer
+ *
+ * sunaudiomixer is an mixer that controls the sound input and output
+ * levels with the Sun Audio interface available in Solaris.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstsunaudiomixer.h"
+
+GST_BOILERPLATE_WITH_INTERFACE (GstSunAudioMixer, gst_sunaudiomixer,
+ GstElement, GST_TYPE_ELEMENT, GstMixer, GST_TYPE_MIXER, gst_sunaudiomixer);
+
+GST_IMPLEMENT_SUNAUDIO_MIXER_CTRL_METHODS (GstSunAudioMixer, gst_sunaudiomixer);
+
+static GstStateChangeReturn gst_sunaudiomixer_change_state (GstElement *
+ element, GstStateChange transition);
+
+static void
+gst_sunaudiomixer_base_init (gpointer klass)
+{
+ gst_element_class_set_details_simple (GST_ELEMENT_CLASS (klass),
+ "Sun Audio Mixer", "Generic/Audio",
+ "Control sound input and output levels with Sun Audio",
+ "Brian Cameron <brian.cameron@sun.com>");
+}
+
+static void
+gst_sunaudiomixer_class_init (GstSunAudioMixerClass * klass)
+{
+ GstElementClass *element_class;
+
+ element_class = (GstElementClass *) klass;
+
+ element_class->change_state = gst_sunaudiomixer_change_state;
+}
+
+static void
+gst_sunaudiomixer_init (GstSunAudioMixer * this,
+ GstSunAudioMixerClass * g_class)
+{
+ this->mixer = NULL;
+}
+
+static GstStateChangeReturn
+gst_sunaudiomixer_change_state (GstElement * element, GstStateChange transition)
+{
+ GstSunAudioMixer *this = GST_SUNAUDIO_MIXER (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ if (!this->mixer) {
+ const char *audiodev;
+
+ audiodev = g_getenv ("AUDIODEV");
+ if (audiodev == NULL) {
+ this->mixer = gst_sunaudiomixer_ctrl_new ("/dev/audioctl");
+ } else {
+ gchar *device = g_strdup_printf ("%sctl", audiodev);
+
+ this->mixer = gst_sunaudiomixer_ctrl_new (device);
+ g_free (device);
+ }
+ }
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ if (this->mixer) {
+ gst_sunaudiomixer_ctrl_free (this->mixer);
+ this->mixer = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (GST_ELEMENT_CLASS (parent_class)->change_state)
+ return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+ return GST_STATE_CHANGE_SUCCESS;
+}
diff --git a/sys/sunaudio/gstsunaudiomixer.h b/sys/sunaudio/gstsunaudiomixer.h
new file mode 100644
index 0000000..7ab6e74
--- /dev/null
+++ b/sys/sunaudio/gstsunaudiomixer.h
@@ -0,0 +1,51 @@
+/*
+ * GStreamer - SunAudio mixer
+ * Copyright (C) 2005,2006 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GST_SUNAUDIO_MIXER_H__
+#define __GST_SUNAUDIO_MIXER_H__
+
+#include "gstsunaudiomixerctrl.h"
+
+G_BEGIN_DECLS
+
+#define GST_SUNAUDIO_MIXER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SUNAUDIO_MIXER,GstSunAudioMixer))
+#define GST_SUNAUDIO_MIXER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SUNAUDIO_MIXER,GstSunAudioMixerClass))
+#define GST_IS_SUNAUDIO_MIXER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SUNAUDIO_MIXER))
+#define GST_IS_SUNAUDIO_MIXER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SUNAUDIO_MIXER))
+#define GST_TYPE_SUNAUDIO_MIXER (gst_sunaudiomixer_get_type())
+
+typedef struct _GstSunAudioMixer GstSunAudioMixer;
+typedef struct _GstSunAudioMixerClass GstSunAudioMixerClass;
+
+struct _GstSunAudioMixer {
+ GstElement parent;
+
+ GstSunAudioMixerCtrl *mixer;
+};
+
+struct _GstSunAudioMixerClass {
+ GstElementClass parent;
+};
+
+GType gst_sunaudiomixer_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_SUNAUDIO_MIXER_H__ */
diff --git a/sys/sunaudio/gstsunaudiomixerctrl.c b/sys/sunaudio/gstsunaudiomixerctrl.c
new file mode 100644
index 0000000..0723134
--- /dev/null
+++ b/sys/sunaudio/gstsunaudiomixerctrl.c
@@ -0,0 +1,585 @@
+/*
+ * GStreamer - SunAudio mixer interface element
+ * Copyright (C) 2005,2006,2008,2009 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ * Copyright (C) 2008 Sun Microsystems, Inc.,
+ * Jan Schmidt <jan.schmidt@sun.com>
+ * Copyright (C) 2009 Sun Microsystems, Inc.,
+ * Garrett D'Amore <garrett.damore@sun.com>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/audio.h>
+#include <sys/mixer.h>
+
+#include <gst/gst-i18n-plugin.h>
+
+#include "gstsunaudiomixerctrl.h"
+#include "gstsunaudiomixertrack.h"
+#include "gstsunaudiomixeroptions.h"
+
+GST_DEBUG_CATEGORY_EXTERN (sunaudio_debug);
+#define GST_CAT_DEFAULT sunaudio_debug
+
+static gboolean
+gst_sunaudiomixer_ctrl_open (GstSunAudioMixerCtrl * mixer)
+{
+ int fd;
+
+ /* First try to open non-blocking */
+ fd = open (mixer->device, O_RDWR | O_NONBLOCK);
+
+ if (fd >= 0) {
+ close (fd);
+ fd = open (mixer->device, O_WRONLY);
+ }
+
+ if (fd == -1) {
+ GST_DEBUG_OBJECT (mixer,
+ "Failed to open mixer device %s, mixing disabled: %s", mixer->device,
+ strerror (errno));
+
+ return FALSE;
+ }
+ mixer->mixer_fd = fd;
+
+ /* Try to set the multiple open flag if we can, but ignore errors */
+ ioctl (mixer->mixer_fd, AUDIO_MIXER_MULTIPLE_OPEN);
+
+ GST_DEBUG_OBJECT (mixer, "Opened mixer device %s", mixer->device);
+
+ return TRUE;
+}
+
+void
+gst_sunaudiomixer_ctrl_build_list (GstSunAudioMixerCtrl * mixer)
+{
+ GstMixerTrack *track;
+ GstMixerOptions *options;
+
+ struct audio_info audioinfo;
+
+ /*
+ * Do not continue appending the same 3 static tracks onto the list
+ */
+ if (mixer->tracklist == NULL) {
+ g_return_if_fail (mixer->mixer_fd != -1);
+
+ /* query available ports */
+ if (ioctl (mixer->mixer_fd, AUDIO_GETINFO, &audioinfo) < 0) {
+ g_warning ("Error getting audio device volume");
+ return;
+ }
+
+ /* Output & should be MASTER when it's the only one. */
+ track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_OUTPUT);
+ mixer->tracklist = g_list_append (mixer->tracklist, track);
+
+ /* Input */
+ track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_RECORD);
+ mixer->tracklist = g_list_append (mixer->tracklist, track);
+
+ /* Monitor */
+ track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_MONITOR);
+ mixer->tracklist = g_list_append (mixer->tracklist, track);
+
+ if (audioinfo.play.avail_ports & AUDIO_SPEAKER) {
+ track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_SPEAKER);
+ mixer->tracklist = g_list_append (mixer->tracklist, track);
+ }
+ if (audioinfo.play.avail_ports & AUDIO_HEADPHONE) {
+ track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_HP);
+ mixer->tracklist = g_list_append (mixer->tracklist, track);
+ }
+ if (audioinfo.play.avail_ports & AUDIO_LINE_OUT) {
+ track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_LINEOUT);
+ mixer->tracklist = g_list_append (mixer->tracklist, track);
+ }
+ if (audioinfo.play.avail_ports & AUDIO_SPDIF_OUT) {
+ track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_SPDIFOUT);
+ mixer->tracklist = g_list_append (mixer->tracklist, track);
+ }
+ if (audioinfo.play.avail_ports & AUDIO_AUX1_OUT) {
+ track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_AUX1OUT);
+ mixer->tracklist = g_list_append (mixer->tracklist, track);
+ }
+ if (audioinfo.play.avail_ports & AUDIO_AUX2_OUT) {
+ track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_AUX2OUT);
+ mixer->tracklist = g_list_append (mixer->tracklist, track);
+ }
+
+ if (audioinfo.record.avail_ports != AUDIO_NONE) {
+ options =
+ gst_sunaudiomixer_options_new (mixer, GST_SUNAUDIO_TRACK_RECSRC);
+ mixer->tracklist = g_list_append (mixer->tracklist, options);
+ }
+ }
+}
+
+GstSunAudioMixerCtrl *
+gst_sunaudiomixer_ctrl_new (const char *device)
+{
+ GstSunAudioMixerCtrl *ret = NULL;
+
+ g_return_val_if_fail (device != NULL, NULL);
+
+ ret = g_new0 (GstSunAudioMixerCtrl, 1);
+
+ ret->device = g_strdup (device);
+ ret->mixer_fd = -1;
+ ret->tracklist = NULL;
+
+ if (!gst_sunaudiomixer_ctrl_open (ret))
+ goto error;
+
+ return ret;
+
+error:
+ if (ret)
+ gst_sunaudiomixer_ctrl_free (ret);
+
+ return NULL;
+}
+
+void
+gst_sunaudiomixer_ctrl_free (GstSunAudioMixerCtrl * mixer)
+{
+ g_return_if_fail (mixer != NULL);
+
+ if (mixer->device) {
+ g_free (mixer->device);
+ mixer->device = NULL;
+ }
+
+ if (mixer->tracklist) {
+ g_list_foreach (mixer->tracklist, (GFunc) g_object_unref, NULL);
+ g_list_free (mixer->tracklist);
+ mixer->tracklist = NULL;
+ }
+
+ if (mixer->mixer_fd != -1) {
+ close (mixer->mixer_fd);
+ mixer->mixer_fd = -1;
+ }
+
+ g_free (mixer);
+}
+
+GstMixerFlags
+gst_sunaudiomixer_ctrl_get_mixer_flags (GstSunAudioMixerCtrl * mixer)
+{
+ return GST_MIXER_FLAG_HAS_WHITELIST | GST_MIXER_FLAG_GROUPING;
+}
+
+const GList *
+gst_sunaudiomixer_ctrl_list_tracks (GstSunAudioMixerCtrl * mixer)
+{
+ gst_sunaudiomixer_ctrl_build_list (mixer);
+
+ return (const GList *) mixer->tracklist;
+}
+
+void
+gst_sunaudiomixer_ctrl_get_volume (GstSunAudioMixerCtrl * mixer,
+ GstMixerTrack * track, gint * volumes)
+{
+ gint gain, balance;
+ float ratio;
+ struct audio_info audioinfo;
+ GstSunAudioMixerTrack *sunaudiotrack;
+
+ g_return_if_fail (GST_IS_SUNAUDIO_MIXER_TRACK (track));
+ sunaudiotrack = GST_SUNAUDIO_MIXER_TRACK (track);
+
+ g_return_if_fail (mixer->mixer_fd != -1);
+
+ if (ioctl (mixer->mixer_fd, AUDIO_GETINFO, &audioinfo) < 0) {
+ g_warning ("Error getting audio device volume");
+ return;
+ }
+
+ balance = AUDIO_MID_BALANCE;
+ gain = 0;
+
+ switch (sunaudiotrack->track_num) {
+ case GST_SUNAUDIO_TRACK_OUTPUT:
+ gain = (int) audioinfo.play.gain;
+ balance = audioinfo.play.balance;
+ break;
+ case GST_SUNAUDIO_TRACK_RECORD:
+ gain = (int) audioinfo.record.gain;
+ balance = audioinfo.record.balance;
+ break;
+ case GST_SUNAUDIO_TRACK_MONITOR:
+ gain = (int) audioinfo.monitor_gain;
+ balance = audioinfo.record.balance;
+ break;
+ case GST_SUNAUDIO_TRACK_SPEAKER:
+ if (audioinfo.play.port & AUDIO_SPEAKER)
+ gain = AUDIO_MAX_GAIN;
+ break;
+ case GST_SUNAUDIO_TRACK_HP:
+ if (audioinfo.play.port & AUDIO_HEADPHONE)
+ gain = AUDIO_MAX_GAIN;
+ break;
+ case GST_SUNAUDIO_TRACK_LINEOUT:
+ if (audioinfo.play.port & AUDIO_LINE_OUT)
+ gain = AUDIO_MAX_GAIN;
+ break;
+ case GST_SUNAUDIO_TRACK_SPDIFOUT:
+ if (audioinfo.play.port & AUDIO_SPDIF_OUT)
+ gain = AUDIO_MAX_GAIN;
+ break;
+ case GST_SUNAUDIO_TRACK_AUX1OUT:
+ if (audioinfo.play.port & AUDIO_AUX1_OUT)
+ gain = AUDIO_MAX_GAIN;
+ break;
+ case GST_SUNAUDIO_TRACK_AUX2OUT:
+ if (audioinfo.play.port & AUDIO_AUX2_OUT)
+ gain = AUDIO_MAX_GAIN;
+ break;
+ default:
+ break;
+ }
+
+ switch (track->num_channels) {
+ case 2:
+ if (balance == AUDIO_MID_BALANCE) {
+ volumes[0] = gain;
+ volumes[1] = gain;
+ } else if (balance < AUDIO_MID_BALANCE) {
+ volumes[0] = gain;
+ ratio = 1 - (float) (AUDIO_MID_BALANCE - balance) /
+ (float) AUDIO_MID_BALANCE;
+ volumes[1] = (int) ((float) gain * ratio + 0.5);
+ } else {
+ volumes[1] = gain;
+ ratio = 1 - (float) (balance - AUDIO_MID_BALANCE) /
+ (float) AUDIO_MID_BALANCE;
+ volumes[0] = (int) ((float) gain * ratio + 0.5);
+ }
+ break;
+ case 1:
+ volumes[0] = gain;
+ break;
+ }
+
+ /* Likewise reset MUTE */
+ if ((sunaudiotrack->track_num == GST_SUNAUDIO_TRACK_OUTPUT
+ && audioinfo.output_muted == 1)
+ || (sunaudiotrack->track_num != GST_SUNAUDIO_TRACK_OUTPUT && gain == 0)) {
+ /*
+ * If MUTE is set, then gain is always 0, so don't bother
+ * resetting our internal value.
+ */
+ track->flags |= GST_MIXER_TRACK_MUTE;
+ } else {
+ sunaudiotrack->gain = gain;
+ sunaudiotrack->balance = balance;
+ track->flags &= ~GST_MIXER_TRACK_MUTE;
+ }
+}
+
+void
+gst_sunaudiomixer_ctrl_set_volume (GstSunAudioMixerCtrl * mixer,
+ GstMixerTrack * track, gint * volumes)
+{
+ gint gain;
+ gint balance;
+ gint l_real_gain;
+ gint r_real_gain;
+ float ratio;
+ struct audio_info audioinfo;
+ GstSunAudioMixerTrack *sunaudiotrack = GST_SUNAUDIO_MIXER_TRACK (track);
+
+ l_real_gain = volumes[0];
+ r_real_gain = volumes[1];
+
+ if (l_real_gain == r_real_gain) {
+ gain = l_real_gain;
+ balance = AUDIO_MID_BALANCE;
+ } else if (l_real_gain < r_real_gain) {
+ gain = r_real_gain;
+ ratio = (float) l_real_gain / (float) r_real_gain;
+ balance =
+ AUDIO_RIGHT_BALANCE - (int) (ratio * (float) AUDIO_MID_BALANCE + 0.5);
+ } else {
+ gain = l_real_gain;
+ ratio = (float) r_real_gain / (float) l_real_gain;
+ balance =
+ AUDIO_LEFT_BALANCE + (int) (ratio * (float) AUDIO_MID_BALANCE + 0.5);
+ }
+
+ sunaudiotrack->gain = gain;
+ sunaudiotrack->balance = balance;
+
+ if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE)) {
+ if (sunaudiotrack->track_num == GST_SUNAUDIO_TRACK_OUTPUT) {
+ return;
+ } else if (gain == 0) {
+ return;
+ } else {
+ /*
+ * If the volume is set to a non-zero value for LINE_IN
+ * or MONITOR, then unset MUTE.
+ */
+ track->flags &= ~GST_MIXER_TRACK_MUTE;
+ }
+ }
+
+ /* Set the volume */
+ AUDIO_INITINFO (&audioinfo);
+
+ switch (sunaudiotrack->track_num) {
+ case GST_SUNAUDIO_TRACK_OUTPUT:
+ audioinfo.play.gain = gain;
+ audioinfo.play.balance = balance;
+ break;
+ case GST_SUNAUDIO_TRACK_RECORD:
+ audioinfo.record.gain = gain;
+ audioinfo.record.balance = balance;
+ break;
+ case GST_SUNAUDIO_TRACK_MONITOR:
+ audioinfo.monitor_gain = gain;
+ audioinfo.record.balance = balance;
+ break;
+ default:
+ break;
+ }
+
+ g_return_if_fail (mixer->mixer_fd != -1);
+
+ if (ioctl (mixer->mixer_fd, AUDIO_SETINFO, &audioinfo) < 0) {
+ g_warning ("Error setting audio device volume");
+ return;
+ }
+}
+
+void
+gst_sunaudiomixer_ctrl_set_mute (GstSunAudioMixerCtrl * mixer,
+ GstMixerTrack * track, gboolean mute)
+{
+ struct audio_info audioinfo;
+ struct audio_info oldinfo;
+ GstSunAudioMixerTrack *sunaudiotrack = GST_SUNAUDIO_MIXER_TRACK (track);
+ gint volume, balance;
+
+ AUDIO_INITINFO (&audioinfo);
+
+ if (ioctl (mixer->mixer_fd, AUDIO_GETINFO, &oldinfo) < 0) {
+ g_warning ("Error getting audio device volume");
+ return;
+ }
+
+ if (mute) {
+ volume = 0;
+ track->flags |= GST_MIXER_TRACK_MUTE;
+ } else {
+ volume = sunaudiotrack->gain;
+ track->flags &= ~GST_MIXER_TRACK_MUTE;
+ }
+
+ balance = sunaudiotrack->balance;
+
+ switch (sunaudiotrack->track_num) {
+ case GST_SUNAUDIO_TRACK_OUTPUT:
+ if (mute)
+ audioinfo.output_muted = 1;
+ else
+ audioinfo.output_muted = 0;
+
+ audioinfo.play.gain = volume;
+ audioinfo.play.balance = balance;
+ break;
+ case GST_SUNAUDIO_TRACK_RECORD:
+ audioinfo.record.gain = volume;
+ audioinfo.record.balance = balance;
+ break;
+ case GST_SUNAUDIO_TRACK_MONITOR:
+ audioinfo.monitor_gain = volume;
+ audioinfo.record.balance = balance;
+ break;
+ case GST_SUNAUDIO_TRACK_SPEAKER:
+ if (mute) {
+ audioinfo.play.port = oldinfo.play.port & ~AUDIO_SPEAKER;
+ } else {
+ audioinfo.play.port = oldinfo.play.port | AUDIO_SPEAKER;
+ }
+ break;
+ case GST_SUNAUDIO_TRACK_HP:
+ if (mute) {
+ audioinfo.play.port = oldinfo.play.port & ~AUDIO_HEADPHONE;
+ } else {
+ audioinfo.play.port = oldinfo.play.port | AUDIO_HEADPHONE;
+ }
+ break;
+ case GST_SUNAUDIO_TRACK_LINEOUT:
+ if (mute) {
+ audioinfo.play.port = oldinfo.play.port & ~AUDIO_LINE_OUT;
+ } else {
+ audioinfo.play.port = oldinfo.play.port | AUDIO_LINE_OUT;
+ }
+ break;
+ case GST_SUNAUDIO_TRACK_SPDIFOUT:
+ if (mute) {
+ audioinfo.play.port = oldinfo.play.port & ~AUDIO_SPDIF_OUT;
+ } else {
+ audioinfo.play.port = oldinfo.play.port | AUDIO_SPDIF_OUT;
+ }
+ break;
+ case GST_SUNAUDIO_TRACK_AUX1OUT:
+ if (mute) {
+ audioinfo.play.port = oldinfo.play.port & ~AUDIO_AUX1_OUT;
+ } else {
+ audioinfo.play.port = oldinfo.play.port | AUDIO_AUX1_OUT;
+ }
+ break;
+ case GST_SUNAUDIO_TRACK_AUX2OUT:
+ if (mute) {
+ audioinfo.play.port = oldinfo.play.port & ~AUDIO_AUX2_OUT;
+ } else {
+ audioinfo.play.port = oldinfo.play.port | AUDIO_AUX2_OUT;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (audioinfo.play.port != ((unsigned) ~0)) {
+ /* mask off ports we can't modify. Hack for broken drivers where mod_ports == 0 */
+ if (oldinfo.play.mod_ports != 0) {
+ audioinfo.play.port &= oldinfo.play.mod_ports;
+ /* and add in any that are forced to be on */
+ audioinfo.play.port |= (oldinfo.play.port & ~oldinfo.play.mod_ports);
+ }
+ }
+ g_return_if_fail (mixer->mixer_fd != -1);
+
+ if (audioinfo.play.port != (guint) (-1) &&
+ audioinfo.play.port != oldinfo.play.port)
+ GST_LOG_OBJECT (mixer, "Changing play port mask to 0x%08x",
+ audioinfo.play.port);
+
+ if (ioctl (mixer->mixer_fd, AUDIO_SETINFO, &audioinfo) < 0) {
+ g_warning ("Error setting audio settings");
+ return;
+ }
+}
+
+void
+gst_sunaudiomixer_ctrl_set_record (GstSunAudioMixerCtrl * mixer,
+ GstMixerTrack * track, gboolean record)
+{
+}
+
+void
+gst_sunaudiomixer_ctrl_set_option (GstSunAudioMixerCtrl * mixer,
+ GstMixerOptions * options, gchar * value)
+{
+ struct audio_info audioinfo;
+ GstMixerTrack *track;
+ GstSunAudioMixerOptions *opts;
+ GQuark q;
+ int i;
+
+ g_return_if_fail (mixer != NULL);
+ g_return_if_fail (mixer->mixer_fd != -1);
+ g_return_if_fail (value != NULL);
+ g_return_if_fail (GST_IS_SUNAUDIO_MIXER_OPTIONS (options));
+
+ track = GST_MIXER_TRACK (options);
+ opts = GST_SUNAUDIO_MIXER_OPTIONS (options);
+
+ if (opts->track_num != GST_SUNAUDIO_TRACK_RECSRC) {
+ g_warning ("set_option not supported on track %s", track->label);
+ return;
+ }
+
+ q = g_quark_try_string (value);
+ if (q == 0) {
+ g_warning ("unknown option '%s'", value);
+ return;
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (opts->names[i] == q) {
+ break;
+ }
+ }
+
+ if (((1 << (i)) & opts->avail) == 0) {
+ g_warning ("Record port %s not available", g_quark_to_string (q));
+ return;
+ }
+
+ AUDIO_INITINFO (&audioinfo);
+ audioinfo.record.port = (1 << (i));
+
+ if (ioctl (mixer->mixer_fd, AUDIO_SETINFO, &audioinfo) < 0) {
+ g_warning ("Error setting audio record port");
+ }
+}
+
+const gchar *
+gst_sunaudiomixer_ctrl_get_option (GstSunAudioMixerCtrl * mixer,
+ GstMixerOptions * options)
+{
+ GstMixerTrack *track;
+ GstSunAudioMixerOptions *opts;
+ struct audio_info audioinfo;
+ int i;
+
+ g_return_val_if_fail (mixer != NULL, NULL);
+ g_return_val_if_fail (mixer->fd != -1, NULL);
+ g_return_val_if_fail (GST_IS_SUNAUDIO_MIXER_OPTIONS (options), NULL);
+
+ track = GST_MIXER_TRACK (options);
+ opts = GST_SUNAUDIO_MIXER_OPTIONS (options);
+
+ g_return_val_if_fail (opts->track_num == GST_SUNAUDIO_TRACK_RECSRC, NULL);
+
+ if (ioctl (mixer->mixer_fd, AUDIO_GETINFO, &audioinfo) < 0) {
+ g_warning ("Error getting audio device settings");
+ return (NULL);
+ }
+
+ for (i = 0; i < 8; i++) {
+ if ((1 << i) == audioinfo.record.port) {
+ const gchar *s = g_quark_to_string (opts->names[i]);
+ GST_DEBUG_OBJECT (mixer, "Getting value for option %d: %s",
+ opts->track_num, s);
+ return (s);
+ }
+ }
+
+ GST_DEBUG_OBJECT (mixer, "Unable to get value for option %d",
+ opts->track_num);
+
+ g_warning ("Record port value %d seems illegal", audioinfo.record.port);
+ return (NULL);
+}
diff --git a/sys/sunaudio/gstsunaudiomixerctrl.h b/sys/sunaudio/gstsunaudiomixerctrl.h
new file mode 100644
index 0000000..d38f02f
--- /dev/null
+++ b/sys/sunaudio/gstsunaudiomixerctrl.h
@@ -0,0 +1,189 @@
+/*
+ * GStreamer - SunAudio mixer interface element.
+ * Copyright (C) 2005,2006,2009 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ * Copyright (C) 2009 Sun Microsystems, Inc.,
+ * Garrett D'Amore <garrett.damore@sun.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GST_SUNAUDIO_MIXER_CTRL_H
+#define __GST_SUNAUDIO_MIXER_CTRL_H
+
+#include <sys/audioio.h>
+
+#include <gst/gst.h>
+#include <gst/interfaces/mixer.h>
+
+G_BEGIN_DECLS
+
+#define GST_SUNAUDIO_MIXER_CTRL(obj) ((GstSunAudioMixerCtrl*)(obj))
+
+typedef struct _GstSunAudioMixerCtrl GstSunAudioMixerCtrl;
+
+struct _GstSunAudioMixerCtrl {
+ GList * tracklist; /* list of available tracks */
+
+ gint fd;
+ gint mixer_fd;
+
+ gchar * device;
+};
+
+GstSunAudioMixerCtrl* gst_sunaudiomixer_ctrl_new (const gchar *device);
+void gst_sunaudiomixer_ctrl_free (GstSunAudioMixerCtrl *mixer);
+
+const GList* gst_sunaudiomixer_ctrl_list_tracks (GstSunAudioMixerCtrl * mixer);
+void gst_sunaudiomixer_ctrl_set_volume (GstSunAudioMixerCtrl * mixer,
+ GstMixerTrack * track,
+ gint * volumes);
+void gst_sunaudiomixer_ctrl_get_volume (GstSunAudioMixerCtrl * mixer,
+ GstMixerTrack * track,
+ gint * volumes);
+void gst_sunaudiomixer_ctrl_set_record (GstSunAudioMixerCtrl * mixer,
+ GstMixerTrack * track,
+ gboolean record);
+void gst_sunaudiomixer_ctrl_set_mute (GstSunAudioMixerCtrl * mixer,
+ GstMixerTrack * track,
+ gboolean mute);
+void gst_sunaudiomixer_ctrl_set_option (GstSunAudioMixerCtrl * mixer,
+ GstMixerOptions * options,
+ gchar * value);
+const gchar * gst_sunaudiomixer_ctrl_get_option (GstSunAudioMixerCtrl * mixer,
+ GstMixerOptions * options);
+GstMixerFlags gst_sunaudiomixer_ctrl_get_mixer_flags (GstSunAudioMixerCtrl *mixer);
+
+#define GST_IMPLEMENT_SUNAUDIO_MIXER_CTRL_METHODS(Type, interface_as_function) \
+static gboolean \
+interface_as_function ## _supported (Type *this, GType iface_type) \
+{ \
+ g_assert (iface_type == GST_TYPE_MIXER); \
+ \
+ return (this->mixer != NULL); \
+} \
+ \
+static const GList* \
+interface_as_function ## _list_tracks (GstMixer * mixer) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_val_if_fail (this != NULL, NULL); \
+ g_return_val_if_fail (this->mixer != NULL, NULL); \
+ \
+ return gst_sunaudiomixer_ctrl_list_tracks (this->mixer); \
+} \
+ \
+static void \
+interface_as_function ## _set_volume (GstMixer * mixer, GstMixerTrack * track, \
+ gint * volumes) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_sunaudiomixer_ctrl_set_volume (this->mixer, track, volumes); \
+} \
+ \
+static void \
+interface_as_function ## _get_volume (GstMixer * mixer, GstMixerTrack * track, \
+ gint * volumes) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_sunaudiomixer_ctrl_get_volume (this->mixer, track, volumes); \
+} \
+ \
+static void \
+interface_as_function ## _set_record (GstMixer * mixer, GstMixerTrack * track, \
+ gboolean record) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_sunaudiomixer_ctrl_set_record (this->mixer, track, record); \
+} \
+ \
+static void \
+interface_as_function ## _set_mute (GstMixer * mixer, GstMixerTrack * track, \
+ gboolean mute) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_sunaudiomixer_ctrl_set_mute (this->mixer, track, mute); \
+} \
+ \
+static const gchar * \
+interface_as_function ## _get_option (GstMixer * mixer, GstMixerOptions * opts) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_val_if_fail (this != NULL, NULL); \
+ g_return_val_if_fail (this->mixer != NULL, NULL); \
+ \
+ return gst_sunaudiomixer_ctrl_get_option (this->mixer, opts); \
+} \
+\
+static void \
+interface_as_function ## _set_option (GstMixer * mixer, GstMixerOptions * opts, \
+ gchar * value) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_if_fail (this != NULL); \
+ g_return_if_fail (this->mixer != NULL); \
+ \
+ gst_sunaudiomixer_ctrl_set_option (this->mixer, opts, value); \
+} \
+\
+static GstMixerFlags \
+interface_as_function ## _get_mixer_flags (GstMixer * mixer) \
+{ \
+ Type *this = (Type*) mixer; \
+ \
+ g_return_val_if_fail (this != NULL, GST_MIXER_FLAG_NONE); \
+ g_return_val_if_fail (this->mixer != NULL, GST_MIXER_FLAG_NONE); \
+ \
+ return gst_sunaudiomixer_ctrl_get_mixer_flags (this->mixer); \
+} \
+ \
+static void \
+interface_as_function ## _interface_init (GstMixerClass * klass) \
+{ \
+ GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE; \
+ \
+ /* set up the interface hooks */ \
+ klass->list_tracks = interface_as_function ## _list_tracks; \
+ klass->set_volume = interface_as_function ## _set_volume; \
+ klass->get_volume = interface_as_function ## _get_volume; \
+ klass->set_mute = interface_as_function ## _set_mute; \
+ klass->set_record = interface_as_function ## _set_record; \
+ klass->get_option = interface_as_function ## _get_option; \
+ klass->set_option = interface_as_function ## _set_option; \
+ klass->get_mixer_flags = interface_as_function ## _get_mixer_flags; \
+}
+
+G_END_DECLS
+
+#endif
diff --git a/sys/sunaudio/gstsunaudiomixeroptions.c b/sys/sunaudio/gstsunaudiomixeroptions.c
new file mode 100644
index 0000000..1fa025b
--- /dev/null
+++ b/sys/sunaudio/gstsunaudiomixeroptions.c
@@ -0,0 +1,157 @@
+/*
+ * GStreamer SunAudio mixer track implementation
+ * Copyright (C) 2009 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ * Garrett D'Amore <garrett.damore@sun.com>
+ *
+ * gstsunaudiomixeroptions.c: Sun Audio mixer options object
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/audio.h>
+#include <sys/mixer.h>
+
+#include <gst/gst-i18n-plugin.h>
+
+#include "gstsunaudiomixeroptions.h"
+#include "gstsunaudiomixertrack.h"
+
+GST_DEBUG_CATEGORY_EXTERN (sunaudio_debug);
+#define GST_CAT_DEFAULT sunaudio_debug
+
+static void gst_sunaudiomixer_options_init (GstSunAudioMixerOptions * sun_opts);
+static void gst_sunaudiomixer_options_class_init (gpointer g_class,
+ gpointer class_data);
+
+static GstMixerOptionsClass *parent_class = NULL;
+
+GType
+gst_sunaudiomixer_options_get_type (void)
+{
+ static GType opts_type = 0;
+
+ if (!opts_type) {
+ static const GTypeInfo opts_info = {
+ sizeof (GstSunAudioMixerOptionsClass),
+ NULL,
+ NULL,
+ gst_sunaudiomixer_options_class_init,
+ NULL,
+ NULL,
+ sizeof (GstSunAudioMixerOptions),
+ 0,
+ (GInstanceInitFunc) gst_sunaudiomixer_options_init,
+ };
+
+ opts_type =
+ g_type_register_static (GST_TYPE_MIXER_OPTIONS,
+ "GstSunAudioMixerOptions", &opts_info, 0);
+ }
+
+ return opts_type;
+}
+
+static void
+gst_sunaudiomixer_options_class_init (gpointer g_class, gpointer class_data)
+{
+ parent_class = g_type_class_peek_parent (g_class);
+}
+
+static void
+gst_sunaudiomixer_options_init (GstSunAudioMixerOptions * sun_opts)
+{
+}
+
+GstMixerOptions *
+gst_sunaudiomixer_options_new (GstSunAudioMixerCtrl * mixer, gint track_num)
+{
+ GstMixerOptions *opts;
+ GstSunAudioMixerOptions *sun_opts;
+ GstMixerTrack *track;
+ const gchar *label;
+ gint i;
+ struct audio_info audioinfo;
+
+ if ((mixer == NULL) || (mixer->mixer_fd == -1)) {
+ g_warning ("mixer not initialized");
+ return NULL;
+ }
+
+ if (track_num != GST_SUNAUDIO_TRACK_RECSRC) {
+ g_warning ("invalid options track");
+ return (NULL);
+ }
+
+ label = N_("Record Source");
+
+ opts = g_object_new (GST_TYPE_SUNAUDIO_MIXER_OPTIONS,
+ "untranslated-label", label, NULL);
+ sun_opts = GST_SUNAUDIO_MIXER_OPTIONS (opts);
+ track = GST_MIXER_TRACK (opts);
+
+ GST_DEBUG_OBJECT (opts, "New mixer options, track %d: %s",
+ track_num, GST_STR_NULL (label));
+
+ /* save off names for the record sources */
+ sun_opts->names[0] = g_quark_from_string (_("Microphone"));
+ sun_opts->names[1] = g_quark_from_string (_("Line In"));
+ sun_opts->names[2] = g_quark_from_string (_("Internal CD"));
+ sun_opts->names[3] = g_quark_from_string (_("SPDIF In"));
+ sun_opts->names[4] = g_quark_from_string (_("AUX 1 In"));
+ sun_opts->names[5] = g_quark_from_string (_("AUX 2 In"));
+ sun_opts->names[6] = g_quark_from_string (_("Codec Loopback"));
+ sun_opts->names[7] = g_quark_from_string (_("SunVTS Loopback"));
+
+ /* set basic information */
+ track->label = g_strdup (_(label));
+ track->num_channels = 0;
+ track->min_volume = 0;
+ track->max_volume = 0;
+ track->flags =
+ GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_WHITELIST |
+ GST_MIXER_TRACK_NO_RECORD;
+
+ if (ioctl (mixer->mixer_fd, AUDIO_GETINFO, &audioinfo) < 0) {
+ g_warning ("Error getting audio device settings");
+ g_object_unref (G_OBJECT (sun_opts));
+ return NULL;
+ }
+
+ sun_opts->avail = audioinfo.record.avail_ports;
+ sun_opts->track_num = track_num;
+
+ for (i = 0; i < 8; i++) {
+ if ((1 << i) & audioinfo.record.avail_ports) {
+ const char *s = g_quark_to_string (sun_opts->names[i]);
+ opts->values = g_list_append (opts->values, g_strdup (s));
+ GST_DEBUG_OBJECT (opts, "option for track %d: %s",
+ track_num, GST_STR_NULL (s));
+ }
+ }
+
+ return opts;
+}
diff --git a/sys/sunaudio/gstsunaudiomixeroptions.h b/sys/sunaudio/gstsunaudiomixeroptions.h
new file mode 100644
index 0000000..fb02b46
--- /dev/null
+++ b/sys/sunaudio/gstsunaudiomixeroptions.h
@@ -0,0 +1,65 @@
+/*
+ * GStreamer SunAudio mixer track implementation
+ * Copyright (C) 2009 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ * Garrett D'Amore <garrett.damore@sun.com>
+ *
+ * gstsunaudiomixeroptions.h: Sun Audio mixer options object
+ *
+ * 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,
+ */
+
+#ifndef __GST_SUNAUDIO_MIXER_OPTIONS_H__
+#define __GST_SUNAUDIO_MIXER_OPTIONS_H__
+
+
+#include "gstsunaudiomixer.h"
+#include <gst/interfaces/mixeroptions.h>
+
+
+G_BEGIN_DECLS
+
+
+#define GST_SUNAUDIO_MIXER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SUNAUDIO_MIXER_OPTIONS, GstSunAudioMixerOptions))
+#define GST_SUNAUDIO_MIXER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SUNAUDIO_MIXER_OPTIONS, GstSunAudioMixerOptionsClass))
+#define GST_IS_SUNAUDIO_MIXER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SUNAUDIO_MIXER_OPTIONS))
+#define GST_IS_SUNAUDIO_MIXER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SUNAUDIO_MIXER_OPTIONS))
+#define GST_TYPE_SUNAUDIO_MIXER_OPTIONS (gst_sunaudiomixer_options_get_type())
+
+
+typedef struct _GstSunAudioMixerOptions GstSunAudioMixerOptions;
+typedef struct _GstSunAudioMixerOptionsClass GstSunAudioMixerOptionsClass;
+
+
+struct _GstSunAudioMixerOptions {
+ GstMixerOptions parent;
+ gint track_num;
+ GQuark names[8]; /* only 8 possible */
+ gint avail; /* mask of avail */
+};
+
+struct _GstSunAudioMixerOptionsClass {
+ GstMixerOptionsClass parent;
+};
+
+
+GType gst_sunaudiomixer_options_get_type (void);
+GstMixerOptions *gst_sunaudiomixer_options_new (GstSunAudioMixerCtrl *mixer, gint track_num);
+
+
+G_END_DECLS
+
+
+#endif /* __GST_SUNAUDIO_MIXER_OPTIONS_H__ */
diff --git a/sys/sunaudio/gstsunaudiomixertrack.c b/sys/sunaudio/gstsunaudiomixertrack.c
new file mode 100644
index 0000000..786ef0d
--- /dev/null
+++ b/sys/sunaudio/gstsunaudiomixertrack.c
@@ -0,0 +1,158 @@
+/*
+ * GStreamer
+ * Copyright (C) 2005,2008, 2009 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ * Copyright (C) 2009 Sun Microsystems, Inc.,
+ * Garrett D'Amore <garrett.damore@sun.com>
+ *
+ * gstsunaudiomixer.c: mixer interface implementation for OSS
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/audioio.h>
+
+#include <gst/gst-i18n-plugin.h>
+
+#include "gstsunaudiomixertrack.h"
+
+GST_DEBUG_CATEGORY_EXTERN (sunaudio_debug);
+#define GST_CAT_DEFAULT sunaudio_debug
+
+#define MASK_BIT_IS_SET(mask, bit) \
+ (mask & (1 << bit))
+
+G_DEFINE_TYPE (GstSunAudioMixerTrack, gst_sunaudiomixer_track,
+ GST_TYPE_MIXER_TRACK);
+
+static void
+gst_sunaudiomixer_track_class_init (GstSunAudioMixerTrackClass * klass)
+{
+ /* nop */
+}
+
+static void
+gst_sunaudiomixer_track_init (GstSunAudioMixerTrack * track)
+{
+ track->gain = 0;
+ track->balance = AUDIO_MID_BALANCE;
+ track->track_num = 0;
+}
+
+GstMixerTrack *
+gst_sunaudiomixer_track_new (GstSunAudioTrackType track_num)
+{
+ const gchar *labels[] = { N_("Volume"),
+ N_("Gain"),
+ N_("Monitor"),
+ N_("Built-in Speaker"),
+ N_("Headphone"),
+ N_("Line Out"),
+ N_("SPDIF Out"),
+ N_("AUX 1 Out"),
+ N_("AUX 2 Out"),
+ };
+
+
+ GstSunAudioMixerTrack *sunaudiotrack;
+ GstMixerTrack *track;
+ const gchar *untranslated_label;
+
+ if ((guint) track_num < G_N_ELEMENTS (labels))
+ untranslated_label = labels[track_num];
+ else
+ untranslated_label = NULL;
+
+ sunaudiotrack = g_object_new (GST_TYPE_SUNAUDIO_MIXER_TRACK,
+ "untranslated-label", untranslated_label, NULL);
+
+ GST_DEBUG_OBJECT (sunaudiotrack, "Creating new mixer track of type %d: %s",
+ track_num, GST_STR_NULL (untranslated_label));
+
+ switch (track_num) {
+ case GST_SUNAUDIO_TRACK_OUTPUT:
+ /* these are sliders */
+ track = GST_MIXER_TRACK (sunaudiotrack);
+ track->label = g_strdup (_(untranslated_label));
+ track->num_channels = 2;
+ track->flags = GST_MIXER_TRACK_OUTPUT | GST_MIXER_TRACK_WHITELIST |
+ GST_MIXER_TRACK_MASTER;
+ track->min_volume = 0;
+ track->max_volume = 255;
+ sunaudiotrack->track_num = track_num;
+ sunaudiotrack->gain = (0 & 0xff);
+ sunaudiotrack->balance = AUDIO_MID_BALANCE;
+ break;
+ case GST_SUNAUDIO_TRACK_RECORD:
+ /* these are sliders */
+ track = GST_MIXER_TRACK (sunaudiotrack);
+ track->label = g_strdup (_(untranslated_label));
+ track->num_channels = 2;
+ track->flags = GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_NO_RECORD |
+ GST_MIXER_TRACK_WHITELIST;
+ track->min_volume = 0;
+ track->max_volume = 255;
+ sunaudiotrack->track_num = track_num;
+ sunaudiotrack->gain = (0 & 0xff);
+ sunaudiotrack->balance = AUDIO_MID_BALANCE;
+ break;
+ case GST_SUNAUDIO_TRACK_MONITOR:
+ /* these are sliders */
+ track = GST_MIXER_TRACK (sunaudiotrack);
+ track->label = g_strdup (_(untranslated_label));
+ track->num_channels = 2;
+ track->flags = GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_NO_RECORD;
+ track->min_volume = 0;
+ track->max_volume = 255;
+ sunaudiotrack->track_num = track_num;
+ sunaudiotrack->gain = (0 & 0xff);
+ sunaudiotrack->balance = AUDIO_MID_BALANCE;
+ break;
+ case GST_SUNAUDIO_TRACK_SPEAKER:
+ case GST_SUNAUDIO_TRACK_HP:
+ case GST_SUNAUDIO_TRACK_LINEOUT:
+ case GST_SUNAUDIO_TRACK_SPDIFOUT:
+ case GST_SUNAUDIO_TRACK_AUX1OUT:
+ case GST_SUNAUDIO_TRACK_AUX2OUT:
+ /* these are switches */
+ track = GST_MIXER_TRACK (sunaudiotrack);
+ track->label = g_strdup (_(untranslated_label));
+ track->num_channels = 0;
+ track->flags = GST_MIXER_TRACK_OUTPUT | GST_MIXER_TRACK_WHITELIST;
+ track->min_volume = 0;
+ track->max_volume = 255;
+ sunaudiotrack->track_num = track_num;
+ sunaudiotrack->gain = (0 & 0xff);
+ sunaudiotrack->balance = AUDIO_MID_BALANCE;
+ break;
+ default:
+ g_warning ("Unknown sun audio track num %d", track_num);
+ track = NULL;
+ }
+
+ return track;
+}
diff --git a/sys/sunaudio/gstsunaudiomixertrack.h b/sys/sunaudio/gstsunaudiomixertrack.h
new file mode 100644
index 0000000..83be9fc
--- /dev/null
+++ b/sys/sunaudio/gstsunaudiomixertrack.h
@@ -0,0 +1,78 @@
+/*
+ * GStreamer SunAudio mixer track implementation
+ * Copyright (C) 2005,2006,2009 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ * Copyright (C) 2009 Sun Microsystems, Inc.,
+ * Garrett D'Amore <garrett.damore@sun.com>
+ *
+ * gstsunaudiomixertrack.h: SunAudio mixer tracks
+ *
+ * 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.
+ */
+
+#ifndef __GST_SUNAUDIO_MIXER_TRACK_H__
+#define __GST_SUNAUDIO_MIXER_TRACK_H__
+
+#include <gst/gst.h>
+#include <gst/interfaces/mixer.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ GST_SUNAUDIO_TRACK_OUTPUT = 0,
+ GST_SUNAUDIO_TRACK_RECORD,
+ GST_SUNAUDIO_TRACK_MONITOR,
+ GST_SUNAUDIO_TRACK_SPEAKER,
+ GST_SUNAUDIO_TRACK_HP,
+ GST_SUNAUDIO_TRACK_LINEOUT,
+ GST_SUNAUDIO_TRACK_SPDIFOUT,
+ GST_SUNAUDIO_TRACK_AUX1OUT,
+ GST_SUNAUDIO_TRACK_AUX2OUT,
+ GST_SUNAUDIO_TRACK_RECSRC
+} GstSunAudioTrackType;
+
+#define GST_TYPE_SUNAUDIO_MIXER_TRACK \
+ (gst_sunaudiomixer_track_get_type ())
+#define GST_SUNAUDIO_MIXER_TRACK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SUNAUDIO_MIXER_TRACK, \
+ GstSunAudioMixerTrack))
+#define GST_SUNAUDIO_MIXER_TRACK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SUNAUDIO_MIXER_TRACK, \
+ GstSunAudioMixerTrackClass))
+#define GST_IS_SUNAUDIO_MIXER_TRACK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SUNAUDIO_MIXER_TRACK))
+#define GST_IS_SUNAUDIO_MIXER_TRACK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SUNAUDIO_MIXER_TRACK))
+
+typedef struct _GstSunAudioMixerTrack {
+ GstMixerTrack parent;
+
+ gint gain;
+ gint balance;
+ GstSunAudioTrackType track_num;
+} GstSunAudioMixerTrack;
+
+typedef struct _GstSunAudioMixerTrackClass {
+ GstMixerTrackClass parent;
+} GstSunAudioMixerTrackClass;
+
+GType gst_sunaudiomixer_track_get_type (void);
+GstMixerTrack* gst_sunaudiomixer_track_new (GstSunAudioTrackType track_num);
+
+G_END_DECLS
+
+#endif /* __GST_SUNAUDIO_MIXER_TRACK_H__ */
diff --git a/sys/sunaudio/gstsunaudiosink.c b/sys/sunaudio/gstsunaudiosink.c
new file mode 100644
index 0000000..2a3cf19
--- /dev/null
+++ b/sys/sunaudio/gstsunaudiosink.c
@@ -0,0 +1,651 @@
+/*
+ * GStreamer - SunAudio sink
+ * Copyright (C) 2004 David A. Schleef <ds@schleef.org>
+ * Copyright (C) 2005,2006 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ * Copyright (C) 2006 Jan Schmidt <thaytan@mad.scientist.com>
+ *
+ * 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-sunaudiosink
+ *
+ * sunaudiosink is an audio sink designed to work with the Sun Audio
+ * interface available in Solaris.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch audiotestsrc volume=0.5 ! sunaudiosink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <fcntl.h>
+#include <string.h>
+#include <stropts.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include "gstsunaudiosink.h"
+
+GST_DEBUG_CATEGORY_EXTERN (sunaudio_debug);
+#define GST_CAT_DEFAULT sunaudio_debug
+
+static void gst_sunaudiosink_base_init (gpointer g_class);
+static void gst_sunaudiosink_class_init (GstSunAudioSinkClass * klass);
+static void gst_sunaudiosink_init (GstSunAudioSink * filter);
+static void gst_sunaudiosink_dispose (GObject * object);
+static void gst_sunaudiosink_finalize (GObject * object);
+
+static void gst_sunaudiosink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_sunaudiosink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static GstCaps *gst_sunaudiosink_getcaps (GstBaseSink * bsink);
+
+static gboolean gst_sunaudiosink_open (GstAudioSink * asink);
+static gboolean gst_sunaudiosink_close (GstAudioSink * asink);
+static gboolean gst_sunaudiosink_prepare (GstAudioSink * asink,
+ GstRingBufferSpec * spec);
+static gboolean gst_sunaudiosink_unprepare (GstAudioSink * asink);
+static guint gst_sunaudiosink_write (GstAudioSink * asink, gpointer data,
+ guint length);
+static guint gst_sunaudiosink_delay (GstAudioSink * asink);
+static void gst_sunaudiosink_reset (GstAudioSink * asink);
+
+#define DEFAULT_DEVICE "/dev/audio"
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+};
+
+static GstStaticPadTemplate gst_sunaudiosink_factory =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-int, "
+ "endianness = (int) BYTE_ORDER, "
+ "signed = (boolean) TRUE, " "width = (int) 16, " "depth = (int) 16, "
+ /* [5510,48000] seems to be a Solaris limit */
+ "rate = (int) [ 5510, 48000 ], " "channels = (int) [ 1, 2 ]")
+ );
+
+static GstElementClass *parent_class = NULL;
+
+GType
+gst_sunaudiosink_get_type (void)
+{
+ static GType plugin_type = 0;
+
+ if (!plugin_type) {
+ static const GTypeInfo plugin_info = {
+ sizeof (GstSunAudioSinkClass),
+ gst_sunaudiosink_base_init,
+ NULL,
+ (GClassInitFunc) gst_sunaudiosink_class_init,
+ NULL,
+ NULL,
+ sizeof (GstSunAudioSink),
+ 0,
+ (GInstanceInitFunc) gst_sunaudiosink_init,
+ };
+
+ plugin_type = g_type_register_static (GST_TYPE_AUDIO_SINK,
+ "GstSunAudioSink", &plugin_info, 0);
+ }
+ return plugin_type;
+}
+
+static void
+gst_sunaudiosink_dispose (GObject * object)
+{
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_sunaudiosink_finalize (GObject * object)
+{
+ GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (object);
+
+ g_mutex_free (sunaudiosink->write_mutex);
+ g_cond_free (sunaudiosink->sleep_cond);
+
+ g_free (sunaudiosink->device);
+
+ if (sunaudiosink->fd != -1) {
+ close (sunaudiosink->fd);
+ sunaudiosink->fd = -1;
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_sunaudiosink_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_add_static_pad_template (element_class,
+ &gst_sunaudiosink_factory);
+ gst_element_class_set_details_simple (element_class, "Sun Audio Sink",
+ "Sink/Audio",
+ "Audio sink for Sun Audio devices",
+ "David A. Schleef <ds@schleef.org>, "
+ "Brian Cameron <brian.cameron@sun.com>");
+}
+
+static void
+gst_sunaudiosink_class_init (GstSunAudioSinkClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSinkClass *gstbasesink_class;
+ GstBaseAudioSinkClass *gstbaseaudiosink_class;
+ GstAudioSinkClass *gstaudiosink_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesink_class = (GstBaseSinkClass *) klass;
+ gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
+ gstaudiosink_class = (GstAudioSinkClass *) klass;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->dispose = gst_sunaudiosink_dispose;
+ gobject_class->finalize = gst_sunaudiosink_finalize;
+
+ gobject_class->set_property = gst_sunaudiosink_set_property;
+ gobject_class->get_property = gst_sunaudiosink_get_property;
+
+ gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_sunaudiosink_getcaps);
+
+ gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_sunaudiosink_open);
+ gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_sunaudiosink_close);
+ gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_sunaudiosink_prepare);
+ gstaudiosink_class->unprepare =
+ GST_DEBUG_FUNCPTR (gst_sunaudiosink_unprepare);
+ gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_sunaudiosink_write);
+ gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_sunaudiosink_delay);
+ gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_sunaudiosink_reset);
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device", "Audio Device (/dev/audio)",
+ DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+gst_sunaudiosink_init (GstSunAudioSink * sunaudiosink)
+{
+ const char *audiodev;
+
+ GST_DEBUG_OBJECT (sunaudiosink, "initializing sunaudiosink");
+
+ sunaudiosink->fd = -1;
+
+ audiodev = g_getenv ("AUDIODEV");
+ if (audiodev == NULL)
+ audiodev = DEFAULT_DEVICE;
+ sunaudiosink->device = g_strdup (audiodev);
+
+ /* mutex and gcond used to control the write method */
+ sunaudiosink->write_mutex = g_mutex_new ();
+ sunaudiosink->sleep_cond = g_cond_new ();
+}
+
+static void
+gst_sunaudiosink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstSunAudioSink *sunaudiosink;
+
+ sunaudiosink = GST_SUNAUDIO_SINK (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ GST_OBJECT_LOCK (sunaudiosink);
+ g_free (sunaudiosink->device);
+ sunaudiosink->device = g_strdup (g_value_get_string (value));
+ GST_OBJECT_UNLOCK (sunaudiosink);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_sunaudiosink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstSunAudioSink *sunaudiosink;
+
+ sunaudiosink = GST_SUNAUDIO_SINK (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ GST_OBJECT_LOCK (sunaudiosink);
+ g_value_set_string (value, sunaudiosink->device);
+ GST_OBJECT_UNLOCK (sunaudiosink);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstCaps *
+gst_sunaudiosink_getcaps (GstBaseSink * bsink)
+{
+ GstPadTemplate *pad_template;
+ GstCaps *caps = NULL;
+ GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (bsink);
+
+ GST_DEBUG_OBJECT (sunaudiosink, "getcaps called");
+
+ pad_template = gst_static_pad_template_get (&gst_sunaudiosink_factory);
+ caps = gst_caps_copy (gst_pad_template_get_caps (pad_template));
+
+ gst_object_unref (pad_template);
+
+ return caps;
+}
+
+static gboolean
+gst_sunaudiosink_open (GstAudioSink * asink)
+{
+ GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (asink);
+ int fd, ret;
+
+ /* First try to open non-blocking */
+ GST_OBJECT_LOCK (sunaudiosink);
+ fd = open (sunaudiosink->device, O_WRONLY | O_NONBLOCK);
+
+ if (fd >= 0) {
+ close (fd);
+ fd = open (sunaudiosink->device, O_WRONLY);
+ }
+
+ if (fd == -1) {
+ GST_OBJECT_UNLOCK (sunaudiosink);
+ goto open_failed;
+ }
+
+ sunaudiosink->fd = fd;
+ GST_OBJECT_UNLOCK (sunaudiosink);
+
+ ret = ioctl (fd, AUDIO_GETDEV, &sunaudiosink->dev);
+ if (ret == -1)
+ goto ioctl_error;
+
+ GST_DEBUG_OBJECT (sunaudiosink, "name %s", sunaudiosink->dev.name);
+ GST_DEBUG_OBJECT (sunaudiosink, "version %s", sunaudiosink->dev.version);
+ GST_DEBUG_OBJECT (sunaudiosink, "config %s", sunaudiosink->dev.config);
+
+ ret = ioctl (fd, AUDIO_GETINFO, &sunaudiosink->info);
+ if (ret == -1)
+ goto ioctl_error;
+
+ GST_DEBUG_OBJECT (sunaudiosink, "monitor_gain %d",
+ sunaudiosink->info.monitor_gain);
+ GST_DEBUG_OBJECT (sunaudiosink, "output_muted %d",
+ sunaudiosink->info.output_muted);
+ GST_DEBUG_OBJECT (sunaudiosink, "hw_features %08x",
+ sunaudiosink->info.hw_features);
+ GST_DEBUG_OBJECT (sunaudiosink, "sw_features %08x",
+ sunaudiosink->info.sw_features);
+ GST_DEBUG_OBJECT (sunaudiosink, "sw_features_enabled %08x",
+ sunaudiosink->info.sw_features_enabled);
+
+ return TRUE;
+
+open_failed:
+ GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, OPEN_WRITE, (NULL),
+ ("can't open connection to Sun Audio device %s", sunaudiosink->device));
+ return FALSE;
+ioctl_error:
+ close (sunaudiosink->fd);
+ GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ return FALSE;
+}
+
+static gboolean
+gst_sunaudiosink_close (GstAudioSink * asink)
+{
+ GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (asink);
+
+ if (sunaudiosink->fd != -1) {
+ close (sunaudiosink->fd);
+ sunaudiosink->fd = -1;
+ }
+ return TRUE;
+}
+
+static gboolean
+gst_sunaudiosink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
+{
+ GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (asink);
+ audio_info_t ainfo;
+ int ret;
+ int ports;
+
+ ret = ioctl (sunaudiosink->fd, AUDIO_GETINFO, &ainfo);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ return FALSE;
+ }
+
+ if (spec->width != 16)
+ return FALSE;
+
+ ports = ainfo.play.port;
+
+ AUDIO_INITINFO (&ainfo);
+
+ ainfo.play.sample_rate = spec->rate;
+ ainfo.play.channels = spec->channels;
+ ainfo.play.precision = spec->width;
+ ainfo.play.encoding = AUDIO_ENCODING_LINEAR;
+ ainfo.play.port = ports;
+
+ /* buffer_time for playback is not implemented in Solaris at the moment,
+ but at some point in the future, it might be */
+ ainfo.play.buffer_size =
+ gst_util_uint64_scale (spec->rate * spec->bytes_per_sample,
+ spec->buffer_time, GST_SECOND / GST_USECOND);
+
+ spec->silence_sample[0] = 0;
+ spec->silence_sample[1] = 0;
+ spec->silence_sample[2] = 0;
+ spec->silence_sample[3] = 0;
+
+ ret = ioctl (sunaudiosink->fd, AUDIO_SETINFO, &ainfo);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ return FALSE;
+ }
+
+ /* Now read back the info to find out the actual buffer size and set
+ segtotal */
+ AUDIO_INITINFO (&ainfo);
+
+ ret = ioctl (sunaudiosink->fd, AUDIO_GETINFO, &ainfo);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ return FALSE;
+ }
+#if 0
+ /* We don't actually use the buffer_size from the sound device, because
+ * it seems it's just bogus sometimes */
+ sunaudiosink->segtotal = spec->segtotal =
+ ainfo.play.buffer_size / spec->segsize;
+#else
+ sunaudiosink->segtotal = spec->segtotal;
+#endif
+ sunaudiosink->segtotal_samples =
+ spec->segtotal * spec->segsize / spec->bytes_per_sample;
+
+ sunaudiosink->segs_written = (gint) ainfo.play.eof;
+ sunaudiosink->samples_written = ainfo.play.samples;
+ sunaudiosink->bytes_per_sample = spec->bytes_per_sample;
+
+ GST_DEBUG_OBJECT (sunaudiosink, "Got device buffer_size of %u",
+ ainfo.play.buffer_size);
+
+ return TRUE;
+}
+
+static gboolean
+gst_sunaudiosink_unprepare (GstAudioSink * asink)
+{
+ return TRUE;
+}
+
+#define LOOP_WHILE_EINTR(v,func) do { (v) = (func); } \
+ while ((v) == -1 && errno == EINTR);
+
+/* Called with the write_mutex held */
+static void
+gst_sunaudio_sink_do_delay (GstSunAudioSink * sink)
+{
+ GstBaseAudioSink *ba_sink = GST_BASE_AUDIO_SINK (sink);
+ GstClockTime total_sleep;
+ GstClockTime max_sleep;
+ gint sleep_usecs;
+ GTimeVal sleep_end;
+ gint err;
+ audio_info_t ainfo;
+ guint diff;
+
+ /* This code below ensures that we don't race any further than buffer_time
+ * ahead of the audio output, by sleeping if the next write call would cause
+ * us to advance too far in the ring-buffer */
+ LOOP_WHILE_EINTR (err, ioctl (sink->fd, AUDIO_GETINFO, &ainfo));
+ if (err < 0)
+ goto write_error;
+
+ /* Compute our offset from the output (copes with overflow) */
+ diff = (guint) (sink->segs_written) - ainfo.play.eof;
+ if (diff > sink->segtotal) {
+ /* This implies that reset did a flush just as the sound device aquired
+ * some buffers internally, and it causes us to be out of sync with the
+ * eof measure. This corrects it */
+ sink->segs_written = ainfo.play.eof;
+ diff = 0;
+ }
+
+ if (diff + 1 < sink->segtotal)
+ return; /* no need to sleep at all */
+
+ /* Never sleep longer than the initial number of undrained segments in the
+ device plus one */
+ total_sleep = 0;
+ max_sleep = (diff + 1) * (ba_sink->latency_time * GST_USECOND);
+ /* sleep for a segment period between .eof polls */
+ sleep_usecs = ba_sink->latency_time;
+
+ /* Current time is our reference point */
+ g_get_current_time (&sleep_end);
+
+ /* If the next segment would take us too far along the ring buffer,
+ * sleep for a bit to free up a slot. If there were a way to find out
+ * when the eof field actually increments, we could use, but the only
+ * notification mechanism seems to be SIGPOLL, which we can't use from
+ * a support library */
+ while (diff + 1 >= sink->segtotal && total_sleep < max_sleep) {
+ GST_LOG_OBJECT (sink, "need to block to drain segment(s). "
+ "Sleeping for %d us", sleep_usecs);
+
+ g_time_val_add (&sleep_end, sleep_usecs);
+
+ if (g_cond_timed_wait (sink->sleep_cond, sink->write_mutex, &sleep_end)) {
+ GST_LOG_OBJECT (sink, "Waking up early due to reset");
+ return; /* Got told to wake up */
+ }
+ total_sleep += (sleep_usecs * GST_USECOND);
+
+ LOOP_WHILE_EINTR (err, ioctl (sink->fd, AUDIO_GETINFO, &ainfo));
+ if (err < 0)
+ goto write_error;
+
+ /* Compute our (new) offset from the output (copes with overflow) */
+ diff = (guint) g_atomic_int_get (&sink->segs_written) - ainfo.play.eof;
+ }
+
+ return;
+
+write_error:
+ GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
+ ("Playback error on device '%s': %s", sink->device, strerror (errno)));
+ return;
+}
+
+static guint
+gst_sunaudiosink_write (GstAudioSink * asink, gpointer data, guint length)
+{
+ GstSunAudioSink *sink = GST_SUNAUDIO_SINK (asink);
+
+ gint bytes_written, err;
+
+ g_mutex_lock (sink->write_mutex);
+ if (sink->flushing) {
+ /* Exit immediately if reset tells us to */
+ g_mutex_unlock (sink->write_mutex);
+ return length;
+ }
+
+ LOOP_WHILE_EINTR (bytes_written, write (sink->fd, data, length));
+ if (bytes_written < 0) {
+ err = bytes_written;
+ goto write_error;
+ }
+
+ /* Increment our sample counter, for delay calcs */
+ g_atomic_int_add (&sink->samples_written, length / sink->bytes_per_sample);
+
+ /* Don't consider the segment written if we didn't output the whole lot yet */
+ if (bytes_written < length) {
+ g_mutex_unlock (sink->write_mutex);
+ return (guint) bytes_written;
+ }
+
+ /* Write a zero length output to trigger increment of the eof field */
+ LOOP_WHILE_EINTR (err, write (sink->fd, NULL, 0));
+ if (err < 0)
+ goto write_error;
+
+ /* Count this extra segment we've written */
+ sink->segs_written += 1;
+
+ /* Now delay so we don't overrun the ring buffer */
+ gst_sunaudio_sink_do_delay (sink);
+
+ g_mutex_unlock (sink->write_mutex);
+ return length;
+
+write_error:
+ g_mutex_unlock (sink->write_mutex);
+
+ GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
+ ("Playback error on device '%s': %s", sink->device, strerror (errno)));
+ return length; /* Say we wrote the segment to let the ringbuffer exit */
+}
+
+/*
+ * Provide the current number of unplayed samples that have been written
+ * to the device */
+static guint
+gst_sunaudiosink_delay (GstAudioSink * asink)
+{
+ GstSunAudioSink *sink = GST_SUNAUDIO_SINK (asink);
+ audio_info_t ainfo;
+ gint ret;
+ guint offset;
+
+ ret = ioctl (sink->fd, AUDIO_GETINFO, &ainfo);
+ if (G_UNLIKELY (ret == -1))
+ return 0;
+
+ offset = (g_atomic_int_get (&sink->samples_written) - ainfo.play.samples);
+
+ /* If the offset is larger than the total ringbuffer size, then we asked
+ between the write call and when samples_written is updated */
+ if (G_UNLIKELY (offset > sink->segtotal_samples))
+ return 0;
+
+ return offset;
+}
+
+static void
+gst_sunaudiosink_reset (GstAudioSink * asink)
+{
+ /* Get current values */
+ GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (asink);
+ audio_info_t ainfo;
+ int ret;
+
+ ret = ioctl (sunaudiosink->fd, AUDIO_GETINFO, &ainfo);
+ if (ret == -1) {
+ /*
+ * Should never happen, but if we couldn't getinfo, then no point
+ * trying to setinfo
+ */
+ GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ return;
+ }
+
+ /*
+ * Pause the audio - so audio stops playing immediately rather than
+ * waiting for the ringbuffer to empty.
+ */
+ ainfo.play.pause = !NULL;
+ ret = ioctl (sunaudiosink->fd, AUDIO_SETINFO, &ainfo);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ }
+
+ /* Flush the audio */
+ ret = ioctl (sunaudiosink->fd, I_FLUSH, FLUSHW);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ }
+
+ /* Now, we take the write_mutex and signal to ensure the write thread
+ * is not busy, and we signal the condition to wake up any sleeper,
+ * then we flush again in case the write wrote something after we flushed,
+ * and finally release the lock and unpause */
+ g_mutex_lock (sunaudiosink->write_mutex);
+ sunaudiosink->flushing = TRUE;
+
+ g_cond_signal (sunaudiosink->sleep_cond);
+
+ ret = ioctl (sunaudiosink->fd, I_FLUSH, FLUSHW);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ }
+
+ /* unpause the audio */
+ ainfo.play.pause = NULL;
+ ret = ioctl (sunaudiosink->fd, AUDIO_SETINFO, &ainfo);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ }
+
+ /* After flushing the audio device, we need to remeasure the sample count
+ * and segments written count so we're in sync with the device */
+
+ sunaudiosink->segs_written = ainfo.play.eof;
+ g_atomic_int_set (&sunaudiosink->samples_written, ainfo.play.samples);
+
+ sunaudiosink->flushing = FALSE;
+ g_mutex_unlock (sunaudiosink->write_mutex);
+}
diff --git a/sys/sunaudio/gstsunaudiosink.h b/sys/sunaudio/gstsunaudiosink.h
new file mode 100644
index 0000000..9454475
--- /dev/null
+++ b/sys/sunaudio/gstsunaudiosink.h
@@ -0,0 +1,78 @@
+/*
+ * GStreamer - SunAudio sink
+ * Copyright (C) 2004 David A. Schleef <ds@schleef.org>
+ * Copyright (C) 2005,2006 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ * Copyright (C) 2006 Jan Schmidt <thaytan@mad.scientist.com>
+ *
+ * gstsunaudiosink.h:
+ *
+ * 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.
+ */
+
+#ifndef __GST_SUNAUDIO_SINK_H__
+#define __GST_SUNAUDIO_SINK_H__
+
+#include <sys/audioio.h>
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosink.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_SUNAUDIO_SINK (gst_sunaudiosink_get_type())
+#define GST_SUNAUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SUNAUDIO_SINK,GstSunAudioSink))
+#define GST_SUNAUDIO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SUNAUDIO_SINK,GstSunAudioSinkClass))
+#define GST_IS_SUNAUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SUNAUDIO_SINK))
+#define GST_IS_SUNAUDIO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SUNAUDIO_SINK))
+
+typedef struct _GstSunAudioSink GstSunAudioSink;
+typedef struct _GstSunAudioSinkClass GstSunAudioSinkClass;
+
+struct _GstSunAudioSink {
+ GstAudioSink sink;
+
+ gchar *device;
+ gint fd;
+
+ audio_device_t dev;
+ audio_info_t info;
+
+ /* Number of segments the ringbuffer is configured for */
+ guint segtotal;
+ guint segtotal_samples;
+
+ /* Number of segments written to the device */
+ gint segs_written;
+ /* Number of samples written to the device */
+ gint samples_written;
+ guint bytes_per_sample;
+
+ /* mutex and gcond used to control the write method */
+ GMutex *write_mutex;
+ GCond *sleep_cond;
+ gboolean flushing;
+};
+
+struct _GstSunAudioSinkClass {
+ GstAudioSinkClass parent_class;
+};
+
+GType gst_sunaudiosink_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_SUNAUDIO_SINK_H__ */
+
diff --git a/sys/sunaudio/gstsunaudiosrc.c b/sys/sunaudio/gstsunaudiosrc.c
new file mode 100644
index 0000000..08282cf
--- /dev/null
+++ b/sys/sunaudio/gstsunaudiosrc.c
@@ -0,0 +1,423 @@
+/*
+ * GStreamer - SunAudio source
+ * Copyright (C) 2005,2006 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ *
+ * gstsunaudiosrc.c:
+ *
+ * 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-sunaudiosrc
+ *
+ * sunaudiosrc is an audio source designed to work with the Sun Audio
+ * interface available in Solaris.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch sunaudiosrc ! wavenc ! filesink location=audio.wav
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <stropts.h>
+#include <sys/mixer.h>
+
+#include "gstsunaudiosrc.h"
+
+GST_DEBUG_CATEGORY_EXTERN (sunaudio_debug);
+#define GST_CAT_DEFAULT sunaudio_debug
+
+static void gst_sunaudiosrc_base_init (gpointer g_class);
+static void gst_sunaudiosrc_class_init (GstSunAudioSrcClass * klass);
+static void gst_sunaudiosrc_init (GstSunAudioSrc * sunaudiosrc,
+ GstSunAudioSrcClass * g_class);
+static void gst_sunaudiosrc_dispose (GObject * object);
+
+static void gst_sunaudiosrc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_sunaudiosrc_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static GstCaps *gst_sunaudiosrc_getcaps (GstBaseSrc * bsrc);
+
+static gboolean gst_sunaudiosrc_open (GstAudioSrc * asrc);
+static gboolean gst_sunaudiosrc_close (GstAudioSrc * asrc);
+static gboolean gst_sunaudiosrc_prepare (GstAudioSrc * asrc,
+ GstRingBufferSpec * spec);
+static gboolean gst_sunaudiosrc_unprepare (GstAudioSrc * asrc);
+static guint gst_sunaudiosrc_read (GstAudioSrc * asrc, gpointer data,
+ guint length);
+static guint gst_sunaudiosrc_delay (GstAudioSrc * asrc);
+static void gst_sunaudiosrc_reset (GstAudioSrc * asrc);
+
+#define DEFAULT_DEVICE "/dev/audio"
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE
+};
+
+GST_BOILERPLATE_WITH_INTERFACE (GstSunAudioSrc, gst_sunaudiosrc,
+ GstAudioSrc, GST_TYPE_AUDIO_SRC, GstMixer, GST_TYPE_MIXER, gst_sunaudiosrc);
+
+GST_IMPLEMENT_SUNAUDIO_MIXER_CTRL_METHODS (GstSunAudioSrc, gst_sunaudiosrc);
+
+static GstStaticPadTemplate gst_sunaudiosrc_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, "
+ /* [5510,48000] seems to be a Solaris limit */
+ "rate = (int) [ 5510, 48000 ], " "channels = (int) [ 1, 2 ]")
+ );
+
+static void
+gst_sunaudiosrc_dispose (GObject * object)
+{
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_sunaudiosrc_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_add_static_pad_template (element_class,
+ &gst_sunaudiosrc_factory);
+ gst_element_class_set_details_simple (element_class, "Sun Audio Source",
+ "Source/Audio",
+ "Audio source for Sun Audio devices",
+ "Brian Cameron <brian.cameron@sun.com>");
+}
+
+static void
+gst_sunaudiosrc_class_init (GstSunAudioSrcClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSrcClass *gstbasesrc_class;
+ GstBaseAudioSrcClass *gstbaseaudiosrc_class;
+ GstAudioSrcClass *gstaudiosrc_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesrc_class = (GstBaseSrcClass *) klass;
+ gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
+ gstaudiosrc_class = (GstAudioSrcClass *) klass;
+
+ gobject_class->dispose = gst_sunaudiosrc_dispose;
+ gobject_class->get_property = gst_sunaudiosrc_get_property;
+ gobject_class->set_property = gst_sunaudiosrc_set_property;
+
+ gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_getcaps);
+
+ gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_open);
+ gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_prepare);
+ gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_unprepare);
+ gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_close);
+ gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_read);
+ gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_delay);
+ gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_reset);
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device",
+ "SunAudio device (usually /dev/audio)", DEFAULT_DEVICE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+gst_sunaudiosrc_init (GstSunAudioSrc * sunaudiosrc,
+ GstSunAudioSrcClass * g_class)
+{
+ const char *audiodev;
+
+ GST_DEBUG_OBJECT (sunaudiosrc, "initializing sunaudiosrc");
+
+ sunaudiosrc->fd = -1;
+
+ audiodev = g_getenv ("AUDIODEV");
+ if (audiodev == NULL)
+ audiodev = DEFAULT_DEVICE;
+ sunaudiosrc->device = g_strdup (audiodev);
+}
+
+static void
+gst_sunaudiosrc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstSunAudioSrc *sunaudiosrc;
+
+ sunaudiosrc = GST_SUNAUDIO_SRC (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ if (sunaudiosrc->device)
+ g_free (sunaudiosrc->device);
+ sunaudiosrc->device = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_sunaudiosrc_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstSunAudioSrc *sunaudiosrc;
+
+ sunaudiosrc = GST_SUNAUDIO_SRC (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_value_set_string (value, sunaudiosrc->device);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstCaps *
+gst_sunaudiosrc_getcaps (GstBaseSrc * bsrc)
+{
+ GstPadTemplate *pad_template;
+ GstCaps *caps = NULL;
+ GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (bsrc);
+
+ GST_DEBUG_OBJECT (sunaudiosrc, "getcaps called");
+
+ pad_template = gst_static_pad_template_get (&gst_sunaudiosrc_factory);
+ caps = gst_caps_copy (gst_pad_template_get_caps (pad_template));
+
+ gst_object_unref (pad_template);
+
+ return caps;
+}
+
+static gboolean
+gst_sunaudiosrc_open (GstAudioSrc * asrc)
+{
+ GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (asrc);
+ int fd, ret;
+
+ fd = open (sunaudiosrc->device, O_RDONLY);
+
+ if (fd == -1) {
+ GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, OPEN_READ, (NULL),
+ ("can't open connection to Sun Audio device %s", sunaudiosrc->device));
+
+ return FALSE;
+ }
+
+ sunaudiosrc->fd = fd;
+
+ ret = ioctl (fd, AUDIO_GETDEV, &sunaudiosrc->dev);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ return FALSE;
+ }
+
+ GST_DEBUG_OBJECT (sunaudiosrc, "name %s", sunaudiosrc->dev.name);
+ GST_DEBUG_OBJECT (sunaudiosrc, "version %s", sunaudiosrc->dev.version);
+ GST_DEBUG_OBJECT (sunaudiosrc, "config %s", sunaudiosrc->dev.config);
+
+ ret = ioctl (fd, AUDIO_GETINFO, &sunaudiosrc->info);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ return FALSE;
+ }
+
+ GST_DEBUG_OBJECT (sunaudiosrc, "monitor_gain %d",
+ sunaudiosrc->info.monitor_gain);
+ GST_DEBUG_OBJECT (sunaudiosrc, "output_muted %d",
+ sunaudiosrc->info.output_muted);
+ GST_DEBUG_OBJECT (sunaudiosrc, "hw_features %08x",
+ sunaudiosrc->info.hw_features);
+ GST_DEBUG_OBJECT (sunaudiosrc, "sw_features %08x",
+ sunaudiosrc->info.sw_features);
+ GST_DEBUG_OBJECT (sunaudiosrc, "sw_features_enabled %08x",
+ sunaudiosrc->info.sw_features_enabled);
+
+ if (!sunaudiosrc->mixer) {
+ const char *audiodev;
+
+ audiodev = g_getenv ("AUDIODEV");
+ if (audiodev == NULL) {
+ sunaudiosrc->mixer = gst_sunaudiomixer_ctrl_new ("/dev/audioctl");
+ } else {
+ gchar *device = g_strdup_printf ("%sctl", audiodev);
+
+ sunaudiosrc->mixer = gst_sunaudiomixer_ctrl_new (device);
+ g_free (device);
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_sunaudiosrc_close (GstAudioSrc * asrc)
+{
+ GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (asrc);
+
+ close (sunaudiosrc->fd);
+ sunaudiosrc->fd = -1;
+
+ if (sunaudiosrc->mixer) {
+ gst_sunaudiomixer_ctrl_free (sunaudiosrc->mixer);
+ sunaudiosrc->mixer = NULL;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_sunaudiosrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
+{
+ GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (asrc);
+ audio_info_t ainfo;
+ int ret;
+ GstSunAudioMixerCtrl *mixer;
+ struct audio_info audioinfo;
+
+ ret = ioctl (sunaudiosrc->fd, AUDIO_GETINFO, &ainfo);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ return FALSE;
+ }
+
+ if (spec->width != 16)
+ return FALSE;
+
+ AUDIO_INITINFO (&ainfo);
+
+ ainfo.record.sample_rate = spec->rate;
+ ainfo.record.precision = spec->width;
+ ainfo.record.channels = spec->channels;
+ ainfo.record.encoding = AUDIO_ENCODING_LINEAR;
+ ainfo.record.buffer_size = spec->buffer_time;
+
+ mixer = sunaudiosrc->mixer;
+
+ if (ioctl (mixer->mixer_fd, AUDIO_GETINFO, &audioinfo) < 0) {
+ g_warning ("Error getting audio device volume");
+ }
+ ainfo.record.port = audioinfo.record.port;
+ ainfo.record.gain = audioinfo.record.gain;
+ ainfo.record.balance = audioinfo.record.balance;
+
+ spec->segsize = 128;
+ spec->segtotal = spec->buffer_time / 128;
+
+ spec->silence_sample[0] = 0;
+ spec->silence_sample[1] = 0;
+ spec->silence_sample[2] = 0;
+ spec->silence_sample[3] = 0;
+
+ ret = ioctl (sunaudiosrc->fd, AUDIO_SETINFO, &ainfo);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ return FALSE;
+ }
+
+
+ ioctl (sunaudiosrc->fd, I_FLUSH, FLUSHR);
+
+ return TRUE;
+}
+
+static gboolean
+gst_sunaudiosrc_unprepare (GstAudioSrc * asrc)
+{
+ return TRUE;
+}
+
+static guint
+gst_sunaudiosrc_read (GstAudioSrc * asrc, gpointer data, guint length)
+{
+ return read (GST_SUNAUDIO_SRC (asrc)->fd, data, length);
+}
+
+static guint
+gst_sunaudiosrc_delay (GstAudioSrc * asrc)
+{
+ return 0;
+}
+
+static void
+gst_sunaudiosrc_reset (GstAudioSrc * asrc)
+{
+ /* Get current values */
+ GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (asrc);
+ audio_info_t ainfo;
+ int ret;
+
+ ret = ioctl (sunaudiosrc->fd, AUDIO_GETINFO, &ainfo);
+ if (ret == -1) {
+ /*
+ * Should never happen, but if we couldn't getinfo, then no point
+ * trying to setinfo
+ */
+ GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ return;
+ }
+
+ /*
+ * Pause the audio - so audio stops playing immediately rather than
+ * waiting for the ringbuffer to empty.
+ */
+ ainfo.record.pause = !NULL;
+ ret = ioctl (sunaudiosrc->fd, AUDIO_SETINFO, &ainfo);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ }
+
+ /* Flush the audio */
+ ret = ioctl (sunaudiosrc->fd, I_FLUSH, FLUSHR);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ }
+
+ /* unpause the audio */
+ ainfo.record.pause = NULL;
+ ret = ioctl (sunaudiosrc->fd, AUDIO_SETINFO, &ainfo);
+ if (ret == -1) {
+ GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
+ strerror (errno)));
+ }
+}
diff --git a/sys/sunaudio/gstsunaudiosrc.h b/sys/sunaudio/gstsunaudiosrc.h
new file mode 100644
index 0000000..95d9613
--- /dev/null
+++ b/sys/sunaudio/gstsunaudiosrc.h
@@ -0,0 +1,67 @@
+/* GStreamer - SunAudio source
+ * Copyright (C) 2005,2006 Sun Microsystems, Inc.,
+ * Brian Cameron <brian.cameron@sun.com>
+ *
+ * gstsunaudiosrc.h:
+ *
+ * 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.
+ */
+
+#ifndef __GST_SUNAUDIO_SRC_H__
+#define __GST_SUNAUDIO_SRC_H__
+
+#include <sys/audioio.h>
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosrc.h>
+
+#include "gstsunaudiomixerctrl.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_SUNAUDIO_SRC (gst_sunaudiosrc_get_type())
+#define GST_SUNAUDIO_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SUNAUDIO_SRC,GstSunAudioSrc))
+#define GST_SUNAUDIO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SUNAUDIO_SRC,GstSunAudioSrcClass))
+#define GST_IS_SUNAUDIO_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SUNAUDIO_SRC))
+#define GST_IS_SUNAUDIO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SUNAUDIO_SRC))
+
+typedef struct _GstSunAudioSrc GstSunAudioSrc;
+typedef struct _GstSunAudioSrcClass GstSunAudioSrcClass;
+
+struct _GstSunAudioSrc {
+ GstAudioSrc src;
+
+ gchar *device;
+ gint fd;
+ gint control_fd;
+
+ audio_device_t dev;
+ audio_info_t info;
+
+ gint bytes_per_sample;
+
+ GstSunAudioMixerCtrl *mixer;
+};
+
+struct _GstSunAudioSrcClass {
+ GstAudioSrcClass parent_class;
+};
+
+GType gst_sunaudiosrc_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_SUNAUDIO_SRC_H__ */
+
diff --git a/sys/v4l2/Makefile.am b/sys/v4l2/Makefile.am
new file mode 100644
index 0000000..a7a99de
--- /dev/null
+++ b/sys/v4l2/Makefile.am
@@ -0,0 +1,60 @@
+plugin_LTLIBRARIES = libgstvideo4linux2.la
+
+if USE_XVIDEO
+xv_source = gstv4l2xoverlay.c
+xv_libs = $(X_LIBS) $(XVIDEO_LIBS)
+else
+xv_source =
+xv_libs =
+endif
+
+libgstvideo4linux2_la_SOURCES = gstv4l2.c \
+ gstv4l2colorbalance.c \
+ gstv4l2object.c \
+ gstv4l2bufferpool.c \
+ gstv4l2src.c \
+ gstv4l2radio.c \
+ gstv4l2tuner.c \
+ gstv4l2vidorient.c \
+ v4l2_calls.c \
+ v4l2src_calls.c \
+ $(xv_source)
+
+if BUILD_EXPERIMENTAL
+libgstvideo4linux2_la_SOURCES += gstv4l2sink.c
+endif
+
+libgstvideo4linux2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \
+ $(GST_BASE_CFLAGS) \
+ $(GST_CONTROLLER_CFLAGS) \
+ $(GST_CFLAGS) \
+ $(X_CFLAGS) \
+ $(LIBV4L2_CFLAGS) \
+ $(GUDEV_CFLAGS)
+
+libgstvideo4linux2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstvideo4linux2_la_LIBTOOLFLAGS = --tag=disable-static
+
+libgstvideo4linux2_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
+ $(GST_BASE_LIBS) \
+ $(GST_CONTROLLER_LIBS) \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstvideo-$(GST_MAJORMINOR) \
+ -lgstinterfaces-$(GST_MAJORMINOR) \
+ $(GST_LIBS) \
+ $(xv_libs) \
+ $(LIBV4L2_LIBS) \
+ $(GUDEV_LIBS)
+
+noinst_HEADERS = \
+ gstv4l2bufferpool.h \
+ gstv4l2colorbalance.h \
+ gstv4l2object.h \
+ gstv4l2sink.h \
+ gstv4l2src.h \
+ gstv4l2radio.h \
+ gstv4l2tuner.h \
+ gstv4l2vidorient.h \
+ gstv4l2xoverlay.h \
+ v4l2_calls.h \
+ v4l2src_calls.h
diff --git a/sys/v4l2/Makefile.in b/sys/v4l2/Makefile.in
new file mode 100644
index 0000000..c9ad860
--- /dev/null
+++ b/sys/v4l2/Makefile.in
@@ -0,0 +1,953 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@BUILD_EXPERIMENTAL_TRUE@am__append_1 = gstv4l2sink.c
+subdir = sys/v4l2
+DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
+ $(top_srcdir)/common/m4/as-auto-alt.m4 \
+ $(top_srcdir)/common/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/common/m4/as-gcc-inline-assembly.m4 \
+ $(top_srcdir)/common/m4/as-objc.m4 \
+ $(top_srcdir)/common/m4/as-python.m4 \
+ $(top_srcdir)/common/m4/as-scrub-include.m4 \
+ $(top_srcdir)/common/m4/as-version.m4 \
+ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
+ $(top_srcdir)/common/m4/gst-arch.m4 \
+ $(top_srcdir)/common/m4/gst-args.m4 \
+ $(top_srcdir)/common/m4/gst-check.m4 \
+ $(top_srcdir)/common/m4/gst-default.m4 \
+ $(top_srcdir)/common/m4/gst-dowhile.m4 \
+ $(top_srcdir)/common/m4/gst-error.m4 \
+ $(top_srcdir)/common/m4/gst-feature.m4 \
+ $(top_srcdir)/common/m4/gst-gettext.m4 \
+ $(top_srcdir)/common/m4/gst-glib2.m4 \
+ $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \
+ $(top_srcdir)/common/m4/gst-platform.m4 \
+ $(top_srcdir)/common/m4/gst-plugin-docs.m4 \
+ $(top_srcdir)/common/m4/gst-plugindir.m4 \
+ $(top_srcdir)/common/m4/gst-x11.m4 \
+ $(top_srcdir)/common/m4/gst.m4 \
+ $(top_srcdir)/common/m4/gtk-doc.m4 \
+ $(top_srcdir)/common/m4/orc.m4 $(top_srcdir)/common/m4/pkg.m4 \
+ $(top_srcdir)/m4/aalib.m4 $(top_srcdir)/m4/esd.m4 \
+ $(top_srcdir)/m4/gconf-2.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gst-fionread.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+@USE_XVIDEO_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \
+@USE_XVIDEO_TRUE@ $(am__DEPENDENCIES_1)
+libgstvideo4linux2_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am__libgstvideo4linux2_la_SOURCES_DIST = gstv4l2.c \
+ gstv4l2colorbalance.c gstv4l2object.c gstv4l2bufferpool.c \
+ gstv4l2src.c gstv4l2radio.c gstv4l2tuner.c gstv4l2vidorient.c \
+ v4l2_calls.c v4l2src_calls.c gstv4l2xoverlay.c gstv4l2sink.c
+@USE_XVIDEO_TRUE@am__objects_1 = \
+@USE_XVIDEO_TRUE@ libgstvideo4linux2_la-gstv4l2xoverlay.lo
+@BUILD_EXPERIMENTAL_TRUE@am__objects_2 = \
+@BUILD_EXPERIMENTAL_TRUE@ libgstvideo4linux2_la-gstv4l2sink.lo
+am_libgstvideo4linux2_la_OBJECTS = libgstvideo4linux2_la-gstv4l2.lo \
+ libgstvideo4linux2_la-gstv4l2colorbalance.lo \
+ libgstvideo4linux2_la-gstv4l2object.lo \
+ libgstvideo4linux2_la-gstv4l2bufferpool.lo \
+ libgstvideo4linux2_la-gstv4l2src.lo \
+ libgstvideo4linux2_la-gstv4l2radio.lo \
+ libgstvideo4linux2_la-gstv4l2tuner.lo \
+ libgstvideo4linux2_la-gstv4l2vidorient.lo \
+ libgstvideo4linux2_la-v4l2_calls.lo \
+ libgstvideo4linux2_la-v4l2src_calls.lo $(am__objects_1) \
+ $(am__objects_2)
+libgstvideo4linux2_la_OBJECTS = $(am_libgstvideo4linux2_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libgstvideo4linux2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) \
+ $(libgstvideo4linux2_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libgstvideo4linux2_la_SOURCES)
+DIST_SOURCES = $(am__libgstvideo4linux2_la_SOURCES_DIST)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+AALIB_CFLAGS = @AALIB_CFLAGS@
+AALIB_CONFIG = @AALIB_CONFIG@
+AALIB_LIBS = @AALIB_LIBS@
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+ANNODEX_CFLAGS = @ANNODEX_CFLAGS@
+ANNODEX_LIBS = @ANNODEX_LIBS@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BZ2_LIBS = @BZ2_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_GOBJECT_CFLAGS = @CAIRO_GOBJECT_CFLAGS@
+CAIRO_GOBJECT_LIBS = @CAIRO_GOBJECT_LIBS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@
+DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@
+DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@
+DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@
+DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@
+DIRECTSOUND_CFLAGS = @DIRECTSOUND_CFLAGS@
+DIRECTSOUND_LDFLAGS = @DIRECTSOUND_LDFLAGS@
+DIRECTSOUND_LIBS = @DIRECTSOUND_LIBS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DV1394_CFLAGS = @DV1394_CFLAGS@
+DV1394_LIBS = @DV1394_LIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ERROR_CFLAGS = @ERROR_CFLAGS@
+ERROR_CXXFLAGS = @ERROR_CXXFLAGS@
+ESD_CFLAGS = @ESD_CFLAGS@
+ESD_CONFIG = @ESD_CONFIG@
+ESD_LIBS = @ESD_LIBS@
+EXEEXT = @EXEEXT@
+FFLAGS = @FFLAGS@
+FGREP = @FGREP@
+FLAC_CFLAGS = @FLAC_CFLAGS@
+FLAC_LIBS = @FLAC_LIBS@
+GCONFTOOL = @GCONFTOOL@
+GCONF_CFLAGS = @GCONF_CFLAGS@
+GCONF_LIBS = @GCONF_LIBS@
+GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+GCOV = @GCOV@
+GCOV_CFLAGS = @GCOV_CFLAGS@
+GCOV_LIBS = @GCOV_LIBS@
+GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@
+GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_PREFIX = @GLIB_PREFIX@
+GLIB_REQ = @GLIB_REQ@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@
+GSTPB_PREFIX = @GSTPB_PREFIX@
+GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@
+GST_BASE_CFLAGS = @GST_BASE_CFLAGS@
+GST_BASE_LIBS = @GST_BASE_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_CONTROLLER_CFLAGS = @GST_CONTROLLER_CFLAGS@
+GST_CONTROLLER_LIBS = @GST_CONTROLLER_LIBS@
+GST_CXXFLAGS = @GST_CXXFLAGS@
+GST_GDP_CFLAGS = @GST_GDP_CFLAGS@
+GST_GDP_LIBS = @GST_GDP_LIBS@
+GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@
+GST_LIBS = @GST_LIBS@
+GST_LICENSE = @GST_LICENSE@
+GST_LT_LDFLAGS = @GST_LT_LDFLAGS@
+GST_MAJORMINOR = @GST_MAJORMINOR@
+GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@
+GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@
+GST_PACKAGE_NAME = @GST_PACKAGE_NAME@
+GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@
+GST_PLUGINS_ALL = @GST_PLUGINS_ALL@
+GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@
+GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@
+GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@
+GST_PLUGINS_DIR = @GST_PLUGINS_DIR@
+GST_PLUGINS_SELECTED = @GST_PLUGINS_SELECTED@
+GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@
+GST_PREFIX = @GST_PREFIX@
+GST_TOOLS_DIR = @GST_TOOLS_DIR@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_X11_CFLAGS = @GTK_X11_CFLAGS@
+GTK_X11_LIBS = @GTK_X11_LIBS@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+HAVE_AVC1394 = @HAVE_AVC1394@
+HAVE_BZ2 = @HAVE_BZ2@
+HAVE_CXX = @HAVE_CXX@
+HAVE_DIRECTSOUND = @HAVE_DIRECTSOUND@
+HAVE_GCONFTOOL = @HAVE_GCONFTOOL@
+HAVE_ROM1394 = @HAVE_ROM1394@
+HAVE_SPEEX = @HAVE_SPEEX@
+HAVE_X = @HAVE_X@
+HAVE_XSHM = @HAVE_XSHM@
+HAVE_ZLIB = @HAVE_ZLIB@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JACK_0_120_1_CFLAGS = @JACK_0_120_1_CFLAGS@
+JACK_0_120_1_LIBS = @JACK_0_120_1_LIBS@
+JACK_1_9_7_CFLAGS = @JACK_1_9_7_CFLAGS@
+JACK_1_9_7_LIBS = @JACK_1_9_7_LIBS@
+JACK_CFLAGS = @JACK_CFLAGS@
+JACK_LIBS = @JACK_LIBS@
+JPEG_LIBS = @JPEG_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCACA_CFLAGS = @LIBCACA_CFLAGS@
+LIBCACA_LIBS = @LIBCACA_LIBS@
+LIBDV_CFLAGS = @LIBDV_CFLAGS@
+LIBDV_LIBS = @LIBDV_LIBS@
+LIBICONV = @LIBICONV@
+LIBIEC61883_CFLAGS = @LIBIEC61883_CFLAGS@
+LIBIEC61883_LIBS = @LIBIEC61883_LIBS@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBPNG_CFLAGS = @LIBPNG_CFLAGS@
+LIBPNG_LIBS = @LIBPNG_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBV4L2_CFLAGS = @LIBV4L2_CFLAGS@
+LIBV4L2_LIBS = @LIBV4L2_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCALEDIR = @LOCALEDIR@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJC_LDFLAGS = @OBJC_LDFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORCC = @ORCC@
+ORCC_FLAGS = @ORCC_FLAGS@
+ORC_CFLAGS = @ORC_CFLAGS@
+ORC_LIBS = @ORC_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@
+PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PLUGINDIR = @PLUGINDIR@
+POSUB = @POSUB@
+PROFILE_CFLAGS = @PROFILE_CFLAGS@
+PULSE_0_9_20_CFLAGS = @PULSE_0_9_20_CFLAGS@
+PULSE_0_9_20_LIBS = @PULSE_0_9_20_LIBS@
+PULSE_1_0_CFLAGS = @PULSE_1_0_CFLAGS@
+PULSE_1_0_LIBS = @PULSE_1_0_LIBS@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RAW1394_CFLAGS = @RAW1394_CFLAGS@
+RAW1394_LIBS = @RAW1394_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHOUT2_CFLAGS = @SHOUT2_CFLAGS@
+SHOUT2_LIBS = @SHOUT2_LIBS@
+SOUP_CFLAGS = @SOUP_CFLAGS@
+SOUP_LIBS = @SOUP_LIBS@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+TAGLIB_CFLAGS = @TAGLIB_CFLAGS@
+TAGLIB_CXXFLAGS = @TAGLIB_CXXFLAGS@
+TAGLIB_LIBS = @TAGLIB_LIBS@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VALGRIND_PATH = @VALGRIND_PATH@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
+WAVPACK_LIBS = @WAVPACK_LIBS@
+WIN32_LIBS = @WIN32_LIBS@
+XDAMAGE_CFLAGS = @XDAMAGE_CFLAGS@
+XDAMAGE_LIBS = @XDAMAGE_LIBS@
+XFIXES_CFLAGS = @XFIXES_CFLAGS@
+XFIXES_LIBS = @XFIXES_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+XMKMF = @XMKMF@
+XSHM_LIBS = @XSHM_LIBS@
+XVIDEO_LIBS = @XVIDEO_LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = libgstvideo4linux2.la
+@USE_XVIDEO_FALSE@xv_source =
+@USE_XVIDEO_TRUE@xv_source = gstv4l2xoverlay.c
+@USE_XVIDEO_FALSE@xv_libs =
+@USE_XVIDEO_TRUE@xv_libs = $(X_LIBS) $(XVIDEO_LIBS)
+libgstvideo4linux2_la_SOURCES = gstv4l2.c gstv4l2colorbalance.c \
+ gstv4l2object.c gstv4l2bufferpool.c gstv4l2src.c \
+ gstv4l2radio.c gstv4l2tuner.c gstv4l2vidorient.c v4l2_calls.c \
+ v4l2src_calls.c $(xv_source) $(am__append_1)
+libgstvideo4linux2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \
+ $(GST_BASE_CFLAGS) \
+ $(GST_CONTROLLER_CFLAGS) \
+ $(GST_CFLAGS) \
+ $(X_CFLAGS) \
+ $(LIBV4L2_CFLAGS) \
+ $(GUDEV_CFLAGS)
+
+libgstvideo4linux2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstvideo4linux2_la_LIBTOOLFLAGS = --tag=disable-static
+libgstvideo4linux2_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
+ $(GST_BASE_LIBS) \
+ $(GST_CONTROLLER_LIBS) \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstvideo-$(GST_MAJORMINOR) \
+ -lgstinterfaces-$(GST_MAJORMINOR) \
+ $(GST_LIBS) \
+ $(xv_libs) \
+ $(LIBV4L2_LIBS) \
+ $(GUDEV_LIBS)
+
+noinst_HEADERS = \
+ gstv4l2bufferpool.h \
+ gstv4l2colorbalance.h \
+ gstv4l2object.h \
+ gstv4l2sink.h \
+ gstv4l2src.h \
+ gstv4l2radio.h \
+ gstv4l2tuner.h \
+ gstv4l2vidorient.h \
+ gstv4l2xoverlay.h \
+ v4l2_calls.h \
+ v4l2src_calls.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sys/v4l2/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu sys/v4l2/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgstvideo4linux2.la: $(libgstvideo4linux2_la_OBJECTS) $(libgstvideo4linux2_la_DEPENDENCIES) $(EXTRA_libgstvideo4linux2_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgstvideo4linux2_la_LINK) -rpath $(plugindir) $(libgstvideo4linux2_la_OBJECTS) $(libgstvideo4linux2_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-gstv4l2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-gstv4l2bufferpool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-gstv4l2colorbalance.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-gstv4l2object.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-gstv4l2radio.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-gstv4l2sink.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-gstv4l2src.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-gstv4l2tuner.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-gstv4l2vidorient.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-gstv4l2xoverlay.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-v4l2_calls.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-v4l2src_calls.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libgstvideo4linux2_la-gstv4l2.lo: gstv4l2.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-gstv4l2.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-gstv4l2.Tpo -c -o libgstvideo4linux2_la-gstv4l2.lo `test -f 'gstv4l2.c' || echo '$(srcdir)/'`gstv4l2.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-gstv4l2.Tpo $(DEPDIR)/libgstvideo4linux2_la-gstv4l2.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstv4l2.c' object='libgstvideo4linux2_la-gstv4l2.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-gstv4l2.lo `test -f 'gstv4l2.c' || echo '$(srcdir)/'`gstv4l2.c
+
+libgstvideo4linux2_la-gstv4l2colorbalance.lo: gstv4l2colorbalance.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-gstv4l2colorbalance.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-gstv4l2colorbalance.Tpo -c -o libgstvideo4linux2_la-gstv4l2colorbalance.lo `test -f 'gstv4l2colorbalance.c' || echo '$(srcdir)/'`gstv4l2colorbalance.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-gstv4l2colorbalance.Tpo $(DEPDIR)/libgstvideo4linux2_la-gstv4l2colorbalance.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstv4l2colorbalance.c' object='libgstvideo4linux2_la-gstv4l2colorbalance.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-gstv4l2colorbalance.lo `test -f 'gstv4l2colorbalance.c' || echo '$(srcdir)/'`gstv4l2colorbalance.c
+
+libgstvideo4linux2_la-gstv4l2object.lo: gstv4l2object.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-gstv4l2object.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-gstv4l2object.Tpo -c -o libgstvideo4linux2_la-gstv4l2object.lo `test -f 'gstv4l2object.c' || echo '$(srcdir)/'`gstv4l2object.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-gstv4l2object.Tpo $(DEPDIR)/libgstvideo4linux2_la-gstv4l2object.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstv4l2object.c' object='libgstvideo4linux2_la-gstv4l2object.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-gstv4l2object.lo `test -f 'gstv4l2object.c' || echo '$(srcdir)/'`gstv4l2object.c
+
+libgstvideo4linux2_la-gstv4l2bufferpool.lo: gstv4l2bufferpool.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-gstv4l2bufferpool.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-gstv4l2bufferpool.Tpo -c -o libgstvideo4linux2_la-gstv4l2bufferpool.lo `test -f 'gstv4l2bufferpool.c' || echo '$(srcdir)/'`gstv4l2bufferpool.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-gstv4l2bufferpool.Tpo $(DEPDIR)/libgstvideo4linux2_la-gstv4l2bufferpool.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstv4l2bufferpool.c' object='libgstvideo4linux2_la-gstv4l2bufferpool.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-gstv4l2bufferpool.lo `test -f 'gstv4l2bufferpool.c' || echo '$(srcdir)/'`gstv4l2bufferpool.c
+
+libgstvideo4linux2_la-gstv4l2src.lo: gstv4l2src.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-gstv4l2src.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-gstv4l2src.Tpo -c -o libgstvideo4linux2_la-gstv4l2src.lo `test -f 'gstv4l2src.c' || echo '$(srcdir)/'`gstv4l2src.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-gstv4l2src.Tpo $(DEPDIR)/libgstvideo4linux2_la-gstv4l2src.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstv4l2src.c' object='libgstvideo4linux2_la-gstv4l2src.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-gstv4l2src.lo `test -f 'gstv4l2src.c' || echo '$(srcdir)/'`gstv4l2src.c
+
+libgstvideo4linux2_la-gstv4l2radio.lo: gstv4l2radio.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-gstv4l2radio.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-gstv4l2radio.Tpo -c -o libgstvideo4linux2_la-gstv4l2radio.lo `test -f 'gstv4l2radio.c' || echo '$(srcdir)/'`gstv4l2radio.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-gstv4l2radio.Tpo $(DEPDIR)/libgstvideo4linux2_la-gstv4l2radio.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstv4l2radio.c' object='libgstvideo4linux2_la-gstv4l2radio.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-gstv4l2radio.lo `test -f 'gstv4l2radio.c' || echo '$(srcdir)/'`gstv4l2radio.c
+
+libgstvideo4linux2_la-gstv4l2tuner.lo: gstv4l2tuner.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-gstv4l2tuner.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-gstv4l2tuner.Tpo -c -o libgstvideo4linux2_la-gstv4l2tuner.lo `test -f 'gstv4l2tuner.c' || echo '$(srcdir)/'`gstv4l2tuner.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-gstv4l2tuner.Tpo $(DEPDIR)/libgstvideo4linux2_la-gstv4l2tuner.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstv4l2tuner.c' object='libgstvideo4linux2_la-gstv4l2tuner.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-gstv4l2tuner.lo `test -f 'gstv4l2tuner.c' || echo '$(srcdir)/'`gstv4l2tuner.c
+
+libgstvideo4linux2_la-gstv4l2vidorient.lo: gstv4l2vidorient.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-gstv4l2vidorient.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-gstv4l2vidorient.Tpo -c -o libgstvideo4linux2_la-gstv4l2vidorient.lo `test -f 'gstv4l2vidorient.c' || echo '$(srcdir)/'`gstv4l2vidorient.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-gstv4l2vidorient.Tpo $(DEPDIR)/libgstvideo4linux2_la-gstv4l2vidorient.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstv4l2vidorient.c' object='libgstvideo4linux2_la-gstv4l2vidorient.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-gstv4l2vidorient.lo `test -f 'gstv4l2vidorient.c' || echo '$(srcdir)/'`gstv4l2vidorient.c
+
+libgstvideo4linux2_la-v4l2_calls.lo: v4l2_calls.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-v4l2_calls.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-v4l2_calls.Tpo -c -o libgstvideo4linux2_la-v4l2_calls.lo `test -f 'v4l2_calls.c' || echo '$(srcdir)/'`v4l2_calls.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-v4l2_calls.Tpo $(DEPDIR)/libgstvideo4linux2_la-v4l2_calls.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='v4l2_calls.c' object='libgstvideo4linux2_la-v4l2_calls.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-v4l2_calls.lo `test -f 'v4l2_calls.c' || echo '$(srcdir)/'`v4l2_calls.c
+
+libgstvideo4linux2_la-v4l2src_calls.lo: v4l2src_calls.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-v4l2src_calls.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-v4l2src_calls.Tpo -c -o libgstvideo4linux2_la-v4l2src_calls.lo `test -f 'v4l2src_calls.c' || echo '$(srcdir)/'`v4l2src_calls.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-v4l2src_calls.Tpo $(DEPDIR)/libgstvideo4linux2_la-v4l2src_calls.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='v4l2src_calls.c' object='libgstvideo4linux2_la-v4l2src_calls.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-v4l2src_calls.lo `test -f 'v4l2src_calls.c' || echo '$(srcdir)/'`v4l2src_calls.c
+
+libgstvideo4linux2_la-gstv4l2xoverlay.lo: gstv4l2xoverlay.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-gstv4l2xoverlay.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-gstv4l2xoverlay.Tpo -c -o libgstvideo4linux2_la-gstv4l2xoverlay.lo `test -f 'gstv4l2xoverlay.c' || echo '$(srcdir)/'`gstv4l2xoverlay.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-gstv4l2xoverlay.Tpo $(DEPDIR)/libgstvideo4linux2_la-gstv4l2xoverlay.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstv4l2xoverlay.c' object='libgstvideo4linux2_la-gstv4l2xoverlay.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-gstv4l2xoverlay.lo `test -f 'gstv4l2xoverlay.c' || echo '$(srcdir)/'`gstv4l2xoverlay.c
+
+libgstvideo4linux2_la-gstv4l2sink.lo: gstv4l2sink.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-gstv4l2sink.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-gstv4l2sink.Tpo -c -o libgstvideo4linux2_la-gstv4l2sink.lo `test -f 'gstv4l2sink.c' || echo '$(srcdir)/'`gstv4l2sink.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-gstv4l2sink.Tpo $(DEPDIR)/libgstvideo4linux2_la-gstv4l2sink.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstv4l2sink.c' object='libgstvideo4linux2_la-gstv4l2sink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-gstv4l2sink.lo `test -f 'gstv4l2sink.c' || echo '$(srcdir)/'`gstv4l2sink.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sys/v4l2/README b/sys/v4l2/README
new file mode 100644
index 0000000..e9c4ab4
--- /dev/null
+++ b/sys/v4l2/README
@@ -0,0 +1,32 @@
+v4l2 plugins
+============
+
+The idea is a bit the same as the idea for the v4l1 plugins. We want
+one generic v4l2element, and a few child objects (probably only two:
+v4l2src and v4l2sink):
+
+ /-------- v4l2src
+v4l2element ---=
+ \-------- v4l2sink
+
+Both v4l2src and v4l2sink have a uncompressed and a compressed
+recording-/playback-mode. Since this is all part of v4l2, the 'client'
+of these elements, i.e. an application using v4l2src/v4l2sink, will
+hardly notice this. All capsnego stuff is done inside, and the plugin
+knows which formats are compressed and which are not.
+
+Please note that the v4l1 and the v4l2 plugins are *not* compatible
+concerning properties. Naming has been kept the same where possible,
+but in some cases, properties had to be removed or added to make
+full use of v4l2.
+
+V4L2 API: http://linux.bytesex.org/v4l2/.
+ http://v4l2spec.bytesex.org/
+ /usr/include/linux/videodev2.h or
+
+Kernel patches available from
+ http://dl.bytesex.org/patches/.
+
+Articles:
+ http://lwn.net/Articles/203924/
+
diff --git a/sys/v4l2/gstv4l2.c b/sys/v4l2/gstv4l2.c
new file mode 100644
index 0000000..95f64db
--- /dev/null
+++ b/sys/v4l2/gstv4l2.c
@@ -0,0 +1,86 @@
+/* GStreamer
+ *
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2.c: plugin for v4l2 elements
+ *
+ * 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 "gst/gst-i18n-plugin.h"
+
+#include <gst/gst.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "gstv4l2object.h"
+#include "gstv4l2src.h"
+#ifdef HAVE_EXPERIMENTAL
+#include "gstv4l2sink.h"
+#endif
+#include "gstv4l2radio.h"
+/* #include "gstv4l2jpegsrc.h" */
+/* #include "gstv4l2mjpegsrc.h" */
+/* #include "gstv4l2mjpegsink.h" */
+
+/* used in v4l2_calls.c and v4l2src_calls.c */
+GST_DEBUG_CATEGORY (v4l2_debug);
+GST_DEBUG_CATEGORY (GST_CAT_PERFORMANCE);
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ GST_DEBUG_CATEGORY_INIT (v4l2_debug, "v4l2", 0, "V4L2 API calls");
+ GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
+
+ /* initialize gst controller library */
+ gst_controller_init (NULL, NULL);
+
+ if (!gst_element_register (plugin, "v4l2src", GST_RANK_PRIMARY,
+ GST_TYPE_V4L2SRC) ||
+#ifdef HAVE_EXPERIMENTAL
+ !gst_element_register (plugin, "v4l2sink", GST_RANK_NONE,
+ GST_TYPE_V4L2SINK) ||
+#endif
+ !gst_element_register (plugin, "v4l2radio", GST_RANK_NONE,
+ GST_TYPE_V4L2RADIO) ||
+ /* !gst_element_register (plugin, "v4l2jpegsrc", */
+ /* GST_RANK_NONE, GST_TYPE_V4L2JPEGSRC) || */
+ /* !gst_element_register (plugin, "v4l2mjpegsrc", */
+ /* GST_RANK_NONE, GST_TYPE_V4L2MJPEGSRC) || */
+ /* !gst_element_register (plugin, "v4l2mjpegsink", */
+ /* GST_RANK_NONE, GST_TYPE_V4L2MJPEGSINK)) */
+ FALSE)
+ return FALSE;
+
+#ifdef ENABLE_NLS
+ setlocale (LC_ALL, "");
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+#endif /* ENABLE_NLS */
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "video4linux2",
+ "elements for Video 4 Linux",
+ plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
new file mode 100644
index 0000000..b81c6a4
--- /dev/null
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -0,0 +1,652 @@
+/* GStreamer
+ *
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ * 2009 Texas Instruments, Inc - http://www.ti.com/
+ *
+ * gstv4l2bufferpool.c V4L2 buffer pool class
+ *
+ * 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 <sys/mman.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "gst/video/video.h"
+
+#include <gstv4l2bufferpool.h>
+#include "gstv4l2src.h"
+#ifdef HAVE_EXPERIMENTAL
+#include "gstv4l2sink.h"
+#endif
+#include "v4l2_calls.h"
+#include "gst/gst-i18n-plugin.h"
+#include <gst/glib-compat-private.h>
+
+/* videodev2.h is not versioned and we can't easily check for the presence
+ * of enum values at compile time, but the V4L2_CAP_VIDEO_OUTPUT_OVERLAY define
+ * was added in the same commit as V4L2_FIELD_INTERLACED_{TB,BT} (b2787845) */
+#ifndef V4L2_CAP_VIDEO_OUTPUT_OVERLAY
+#define V4L2_FIELD_INTERLACED_TB 8
+#define V4L2_FIELD_INTERLACED_BT 9
+#endif
+
+
+GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
+#define GST_CAT_DEFAULT v4l2_debug
+
+
+/*
+ * GstV4l2Buffer:
+ */
+
+static GstBufferClass *v4l2buffer_parent_class = NULL;
+
+static void
+gst_v4l2_buffer_finalize (GstV4l2Buffer * buffer)
+{
+ GstV4l2BufferPool *pool;
+ gboolean resuscitated = FALSE;
+ gint index;
+
+ pool = buffer->pool;
+
+ index = buffer->vbuffer.index;
+
+ GST_LOG_OBJECT (pool->v4l2elem, "finalizing buffer %p %d", buffer, index);
+
+ GST_V4L2_BUFFER_POOL_LOCK (pool);
+ if (pool->running) {
+ if (pool->requeuebuf) {
+ if (!gst_v4l2_buffer_pool_qbuf (pool, buffer)) {
+ GST_WARNING ("could not requeue buffer %p %d", buffer, index);
+ } else {
+ resuscitated = TRUE;
+ }
+ } else {
+ resuscitated = TRUE;
+ /* XXX double check this... I think it is ok to not synchronize this
+ * w.r.t. destruction of the pool, since the buffer is still live and
+ * the buffer holds a ref to the pool..
+ */
+ g_async_queue_push (pool->avail_buffers, buffer);
+ }
+ } else {
+ GST_LOG_OBJECT (pool->v4l2elem, "the pool is shutting down");
+ }
+
+ if (resuscitated) {
+ /* FIXME: check that the caps didn't change */
+ GST_LOG_OBJECT (pool->v4l2elem, "reviving buffer %p, %d", buffer, index);
+ gst_buffer_ref (GST_BUFFER (buffer));
+ GST_BUFFER_SIZE (buffer) = 0;
+ pool->buffers[index] = buffer;
+ }
+
+ GST_V4L2_BUFFER_POOL_UNLOCK (pool);
+
+ if (!resuscitated) {
+ GST_LOG_OBJECT (pool->v4l2elem,
+ "buffer %p (data %p, len %u) not recovered, unmapping",
+ buffer, GST_BUFFER_DATA (buffer), buffer->vbuffer.length);
+ gst_mini_object_unref (GST_MINI_OBJECT (pool));
+ v4l2_munmap ((void *) GST_BUFFER_DATA (buffer), buffer->vbuffer.length);
+
+ GST_MINI_OBJECT_CLASS (v4l2buffer_parent_class)->finalize (GST_MINI_OBJECT
+ (buffer));
+ }
+}
+
+static void
+gst_v4l2_buffer_class_init (gpointer g_class, gpointer class_data)
+{
+ GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
+
+ v4l2buffer_parent_class = g_type_class_peek_parent (g_class);
+
+ mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
+ gst_v4l2_buffer_finalize;
+}
+
+GType
+gst_v4l2_buffer_get_type (void)
+{
+ static GType _gst_v4l2_buffer_type;
+
+ if (G_UNLIKELY (_gst_v4l2_buffer_type == 0)) {
+ static const GTypeInfo v4l2_buffer_info = {
+ sizeof (GstBufferClass),
+ NULL,
+ NULL,
+ gst_v4l2_buffer_class_init,
+ NULL,
+ NULL,
+ sizeof (GstV4l2Buffer),
+ 0,
+ NULL,
+ NULL
+ };
+ _gst_v4l2_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
+ "GstV4l2Buffer", &v4l2_buffer_info, 0);
+ }
+ return _gst_v4l2_buffer_type;
+}
+
+static GstV4l2Buffer *
+gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
+{
+ GstV4l2Buffer *ret;
+ guint8 *data;
+
+ ret = (GstV4l2Buffer *) gst_mini_object_new (GST_TYPE_V4L2_BUFFER);
+
+ GST_LOG_OBJECT (pool->v4l2elem, "creating buffer %u, %p in pool %p", index,
+ ret, pool);
+
+ ret->pool =
+ (GstV4l2BufferPool *) gst_mini_object_ref (GST_MINI_OBJECT (pool));
+
+ ret->vbuffer.index = index;
+ ret->vbuffer.type = pool->type;
+ ret->vbuffer.memory = V4L2_MEMORY_MMAP;
+
+ if (v4l2_ioctl (pool->video_fd, VIDIOC_QUERYBUF, &ret->vbuffer) < 0)
+ goto querybuf_failed;
+
+ GST_LOG_OBJECT (pool->v4l2elem, " index: %u", ret->vbuffer.index);
+ GST_LOG_OBJECT (pool->v4l2elem, " type: %d", ret->vbuffer.type);
+ GST_LOG_OBJECT (pool->v4l2elem, " bytesused: %u", ret->vbuffer.bytesused);
+ GST_LOG_OBJECT (pool->v4l2elem, " flags: %08x", ret->vbuffer.flags);
+ GST_LOG_OBJECT (pool->v4l2elem, " field: %d", ret->vbuffer.field);
+ GST_LOG_OBJECT (pool->v4l2elem, " memory: %d", ret->vbuffer.memory);
+ if (ret->vbuffer.memory == V4L2_MEMORY_MMAP)
+ GST_LOG_OBJECT (pool->v4l2elem, " MMAP offset: %u",
+ ret->vbuffer.m.offset);
+ GST_LOG_OBJECT (pool->v4l2elem, " length: %u", ret->vbuffer.length);
+ GST_LOG_OBJECT (pool->v4l2elem, " input: %u", ret->vbuffer.input);
+
+ data = (guint8 *) v4l2_mmap (0, ret->vbuffer.length,
+ PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
+ ret->vbuffer.m.offset);
+
+ if (data == MAP_FAILED)
+ goto mmap_failed;
+
+ GST_BUFFER_DATA (ret) = data;
+ GST_BUFFER_SIZE (ret) = ret->vbuffer.length;
+
+ GST_BUFFER_FLAG_SET (ret, GST_BUFFER_FLAG_READONLY);
+
+ gst_buffer_set_caps (GST_BUFFER (ret), caps);
+
+ return ret;
+
+ /* ERRORS */
+querybuf_failed:
+ {
+ gint errnosave = errno;
+
+ GST_WARNING ("Failed QUERYBUF: %s", g_strerror (errnosave));
+ gst_buffer_unref (GST_BUFFER (ret));
+ errno = errnosave;
+ return NULL;
+ }
+mmap_failed:
+ {
+ gint errnosave = errno;
+
+ GST_WARNING ("Failed to mmap: %s", g_strerror (errnosave));
+ gst_buffer_unref (GST_BUFFER (ret));
+ errno = errnosave;
+ return NULL;
+ }
+}
+
+
+/*
+ * GstV4l2BufferPool:
+ */
+
+static GstMiniObjectClass *buffer_pool_parent_class = NULL;
+
+static void
+gst_v4l2_buffer_pool_finalize (GstV4l2BufferPool * pool)
+{
+ g_mutex_free (pool->lock);
+ pool->lock = NULL;
+
+ g_async_queue_unref (pool->avail_buffers);
+ pool->avail_buffers = NULL;
+
+ if (pool->video_fd >= 0)
+ v4l2_close (pool->video_fd);
+
+ if (pool->buffers) {
+ g_free (pool->buffers);
+ pool->buffers = NULL;
+ }
+
+ GST_MINI_OBJECT_CLASS (buffer_pool_parent_class)->finalize (GST_MINI_OBJECT
+ (pool));
+}
+
+static void
+gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool, gpointer g_class)
+{
+ pool->lock = g_mutex_new ();
+ pool->running = FALSE;
+ pool->num_live_buffers = 0;
+}
+
+static void
+gst_v4l2_buffer_pool_class_init (gpointer g_class, gpointer class_data)
+{
+ GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
+
+ buffer_pool_parent_class = g_type_class_peek_parent (g_class);
+
+ mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
+ gst_v4l2_buffer_pool_finalize;
+}
+
+GType
+gst_v4l2_buffer_pool_get_type (void)
+{
+ static GType _gst_v4l2_buffer_pool_type;
+
+ if (G_UNLIKELY (_gst_v4l2_buffer_pool_type == 0)) {
+ static const GTypeInfo v4l2_buffer_pool_info = {
+ sizeof (GstMiniObjectClass),
+ NULL,
+ NULL,
+ gst_v4l2_buffer_pool_class_init,
+ NULL,
+ NULL,
+ sizeof (GstV4l2BufferPool),
+ 0,
+ (GInstanceInitFunc) gst_v4l2_buffer_pool_init,
+ NULL
+ };
+ _gst_v4l2_buffer_pool_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
+ "GstV4l2BufferPool", &v4l2_buffer_pool_info, 0);
+ }
+ return _gst_v4l2_buffer_pool_type;
+}
+
+
+/* this is somewhat of a hack.. but better to keep the hack in
+ * one place than copy/pasting it around..
+ */
+static GstV4l2Object *
+get_v4l2_object (GstElement * v4l2elem)
+{
+ GstV4l2Object *v4l2object = NULL;
+ if (GST_IS_V4L2SRC (v4l2elem)) {
+ v4l2object = (GST_V4L2SRC (v4l2elem))->v4l2object;
+#ifdef HAVE_EXPERIMENTAL
+ } else if (GST_IS_V4L2SINK (v4l2elem)) {
+ v4l2object = (GST_V4L2SINK (v4l2elem))->v4l2object;
+#endif
+ } else {
+ GST_ERROR_OBJECT (v4l2elem, "unknown v4l2 element");
+ }
+ return v4l2object;
+}
+
+
+
+/**
+ * gst_v4l2_buffer_pool_new:
+ * @v4l2elem: the v4l2 element (src or sink) that owns this pool
+ * @fd: the video device file descriptor
+ * @num_buffers: the requested number of buffers in the pool
+ * @caps: the caps to set on the buffer
+ * @requeuebuf: if %TRUE, and if the pool is still in the running state, a
+ * buffer with no remaining references is immediately passed back to v4l2
+ * (VIDIOC_QBUF), otherwise it is returned to the pool of available buffers
+ * (which can be accessed via gst_v4l2_buffer_pool_get().
+ *
+ * Construct a new buffer pool.
+ *
+ * Returns: the new pool, use gst_v4l2_buffer_pool_destroy() to free resources
+ */
+GstV4l2BufferPool *
+gst_v4l2_buffer_pool_new (GstElement * v4l2elem, gint fd, gint num_buffers,
+ GstCaps * caps, gboolean requeuebuf, enum v4l2_buf_type type)
+{
+ GstV4l2BufferPool *pool;
+ gint n;
+ struct v4l2_requestbuffers breq;
+
+ pool = (GstV4l2BufferPool *) gst_mini_object_new (GST_TYPE_V4L2_BUFFER_POOL);
+
+ pool->video_fd = v4l2_dup (fd);
+ if (pool->video_fd < 0)
+ goto dup_failed;
+
+
+ /* first, lets request buffers, and see how many we can get: */
+ GST_DEBUG_OBJECT (v4l2elem, "STREAMING, requesting %d MMAP buffers",
+ num_buffers);
+
+ memset (&breq, 0, sizeof (struct v4l2_requestbuffers));
+ breq.type = type;
+ breq.count = num_buffers;
+ breq.memory = V4L2_MEMORY_MMAP;
+
+ if (v4l2_ioctl (fd, VIDIOC_REQBUFS, &breq) < 0)
+ goto reqbufs_failed;
+
+ GST_LOG_OBJECT (v4l2elem, " count: %u", breq.count);
+ GST_LOG_OBJECT (v4l2elem, " type: %d", breq.type);
+ GST_LOG_OBJECT (v4l2elem, " memory: %d", breq.memory);
+
+ if (breq.count < GST_V4L2_MIN_BUFFERS)
+ goto no_buffers;
+
+ if (num_buffers != breq.count) {
+ GST_WARNING_OBJECT (v4l2elem, "using %u buffers instead", breq.count);
+ num_buffers = breq.count;
+ }
+
+ pool->v4l2elem = v4l2elem;
+ pool->requeuebuf = requeuebuf;
+ pool->type = type;
+ pool->buffer_count = num_buffers;
+ pool->buffers = g_new0 (GstV4l2Buffer *, num_buffers);
+ pool->avail_buffers = g_async_queue_new ();
+
+ /* now, map the buffers: */
+ for (n = 0; n < num_buffers; n++) {
+ pool->buffers[n] = gst_v4l2_buffer_new (pool, n, caps);
+ if (!pool->buffers[n])
+ goto buffer_new_failed;
+ pool->num_live_buffers++;
+ g_async_queue_push (pool->avail_buffers, pool->buffers[n]);
+ }
+
+ return pool;
+
+ /* ERRORS */
+dup_failed:
+ {
+ gint errnosave = errno;
+
+ gst_mini_object_unref (GST_MINI_OBJECT (pool));
+
+ errno = errnosave;
+
+ return NULL;
+ }
+reqbufs_failed:
+ {
+ GstV4l2Object *v4l2object = get_v4l2_object (v4l2elem);
+ GST_ELEMENT_ERROR (v4l2elem, RESOURCE, READ,
+ (_("Could not get buffers from device '%s'."),
+ v4l2object->videodev),
+ ("error requesting %d buffers: %s", num_buffers, g_strerror (errno)));
+ return NULL;
+ }
+no_buffers:
+ {
+ GstV4l2Object *v4l2object = get_v4l2_object (v4l2elem);
+ GST_ELEMENT_ERROR (v4l2elem, RESOURCE, READ,
+ (_("Could not get enough buffers from device '%s'."),
+ v4l2object->videodev),
+ ("we received %d from device '%s', we want at least %d",
+ breq.count, v4l2object->videodev, GST_V4L2_MIN_BUFFERS));
+ return NULL;
+ }
+buffer_new_failed:
+ {
+ gint errnosave = errno;
+
+ gst_v4l2_buffer_pool_destroy (pool);
+
+ errno = errnosave;
+
+ return NULL;
+ }
+}
+
+/**
+ * gst_v4l2_buffer_pool_destroy:
+ * @pool: the pool
+ *
+ * Free all resources in the pool and the pool itself.
+ */
+void
+gst_v4l2_buffer_pool_destroy (GstV4l2BufferPool * pool)
+{
+ gint n;
+
+ GST_V4L2_BUFFER_POOL_LOCK (pool);
+ pool->running = FALSE;
+ GST_V4L2_BUFFER_POOL_UNLOCK (pool);
+
+ GST_DEBUG_OBJECT (pool->v4l2elem, "destroy pool");
+
+ /* after this point, no more buffers will be queued or dequeued; no buffer
+ * from pool->buffers that is NULL will be set to a buffer, and no buffer that
+ * is not NULL will be pushed out. */
+
+ /* miniobjects have no dispose, so they can't break ref-cycles, as buffers ref
+ * the pool, we need to unref the buffer to properly finalize te pool */
+ for (n = 0; n < pool->buffer_count; n++) {
+ GstBuffer *buf;
+
+ GST_V4L2_BUFFER_POOL_LOCK (pool);
+ buf = GST_BUFFER (pool->buffers[n]);
+ GST_V4L2_BUFFER_POOL_UNLOCK (pool);
+
+ if (buf)
+ /* we own the ref if the buffer is in pool->buffers; drop it. */
+ gst_buffer_unref (buf);
+ }
+
+ gst_mini_object_unref (GST_MINI_OBJECT (pool));
+}
+
+/**
+ * gst_v4l2_buffer_pool_get:
+ * @pool: the "this" object
+ * @blocking: should this call suspend until there is a buffer available
+ * in the buffer pool?
+ *
+ * Get an available buffer in the pool
+ */
+GstV4l2Buffer *
+gst_v4l2_buffer_pool_get (GstV4l2BufferPool * pool, gboolean blocking)
+{
+ GstV4l2Buffer *buf;
+
+ if (blocking) {
+ buf = g_async_queue_pop (pool->avail_buffers);
+ } else {
+ buf = g_async_queue_try_pop (pool->avail_buffers);
+ }
+
+ if (buf) {
+ GST_V4L2_BUFFER_POOL_LOCK (pool);
+ GST_BUFFER_SIZE (buf) = buf->vbuffer.length;
+ GST_BUFFER_FLAG_UNSET (buf, 0xffffffff);
+ GST_V4L2_BUFFER_POOL_UNLOCK (pool);
+ }
+
+ pool->running = TRUE;
+
+ return buf;
+}
+
+
+/**
+ * gst_v4l2_buffer_pool_qbuf:
+ * @pool: the pool
+ * @buf: the buffer to queue
+ *
+ * Queue a buffer to the driver
+ *
+ * Returns: %TRUE for success
+ */
+gboolean
+gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstV4l2Buffer * buf)
+{
+ GST_LOG_OBJECT (pool->v4l2elem, "enqueue pool buffer %d", buf->vbuffer.index);
+
+ if (v4l2_ioctl (pool->video_fd, VIDIOC_QBUF, &buf->vbuffer) < 0)
+ return FALSE;
+
+ pool->num_live_buffers--;
+ GST_DEBUG_OBJECT (pool->v4l2elem, "num_live_buffers--: %d",
+ pool->num_live_buffers);
+
+ return TRUE;
+}
+
+/**
+ * gst_v4l2_buffer_pool_dqbuf:
+ * @pool: the pool
+ *
+ * Dequeue a buffer from the driver. Some generic error handling is done in
+ * this function, but any error handling specific to v4l2src (capture) or
+ * v4l2sink (output) can be done outside this function by checking 'errno'
+ *
+ * Returns: a buffer
+ */
+GstV4l2Buffer *
+gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool)
+{
+ GstV4l2Object *v4l2object = get_v4l2_object (pool->v4l2elem);
+ GstV4l2Buffer *pool_buffer;
+ struct v4l2_buffer buffer;
+
+ memset (&buffer, 0x00, sizeof (buffer));
+ buffer.type = pool->type;
+ buffer.memory = V4L2_MEMORY_MMAP;
+
+
+ if (v4l2_ioctl (pool->video_fd, VIDIOC_DQBUF, &buffer) >= 0) {
+
+ GST_V4L2_BUFFER_POOL_LOCK (pool);
+
+ /* get our GstBuffer with that index from the pool, if the buffer was
+ * outstanding we have a serious problem.
+ */
+ pool_buffer = pool->buffers[buffer.index];
+
+ if (pool_buffer == NULL) {
+ GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, FAILED,
+ (_("Failed trying to get video frames from device '%s'."),
+ v4l2object->videodev),
+ (_("No free buffers found in the pool at index %d."), buffer.index));
+ GST_V4L2_BUFFER_POOL_UNLOCK (pool);
+ return NULL;
+ }
+
+ GST_LOG_OBJECT (pool->v4l2elem,
+ "grabbed frame %d (ix=%d), flags %08x, pool-ct=%d, buffer=%p",
+ buffer.sequence, buffer.index, buffer.flags, pool->num_live_buffers,
+ pool_buffer);
+
+ pool->num_live_buffers++;
+ GST_DEBUG_OBJECT (pool->v4l2elem, "num_live_buffers++: %d",
+ pool->num_live_buffers);
+
+ /* set top/bottom field first if v4l2_buffer has the information */
+ if (buffer.field == V4L2_FIELD_INTERLACED_TB)
+ GST_BUFFER_FLAG_SET (pool_buffer, GST_VIDEO_BUFFER_TFF);
+ if (buffer.field == V4L2_FIELD_INTERLACED_BT)
+ GST_BUFFER_FLAG_UNSET (pool_buffer, GST_VIDEO_BUFFER_TFF);
+
+ /* this can change at every frame, esp. with jpeg */
+ GST_BUFFER_SIZE (pool_buffer) = buffer.bytesused;
+
+ GST_V4L2_BUFFER_POOL_UNLOCK (pool);
+
+ return pool_buffer;
+ }
+
+
+ GST_WARNING_OBJECT (pool->v4l2elem,
+ "problem grabbing frame %d (ix=%d), pool-ct=%d, buf.flags=%d",
+ buffer.sequence, buffer.index,
+ GST_MINI_OBJECT_REFCOUNT (pool), buffer.flags);
+
+ switch (errno) {
+ case EAGAIN:
+ GST_WARNING_OBJECT (pool->v4l2elem,
+ "Non-blocking I/O has been selected using O_NONBLOCK and"
+ " no buffer was in the outgoing queue. device %s",
+ v4l2object->videodev);
+ break;
+ case EINVAL:
+ GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, FAILED,
+ (_("Failed trying to get video frames from device '%s'."),
+ v4l2object->videodev),
+ (_("The buffer type is not supported, or the index is out of bounds,"
+ " or no buffers have been allocated yet, or the userptr"
+ " or length are invalid. device %s"), v4l2object->videodev));
+ break;
+ case ENOMEM:
+ GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, FAILED,
+ (_("Failed trying to get video frames from device '%s'. Not enough memory."), v4l2object->videodev), (_("insufficient memory to enqueue a user pointer buffer. device %s."), v4l2object->videodev));
+ break;
+ case EIO:
+ GST_INFO_OBJECT (pool->v4l2elem,
+ "VIDIOC_DQBUF failed due to an internal error."
+ " Can also indicate temporary problems like signal loss."
+ " Note the driver might dequeue an (empty) buffer despite"
+ " returning an error, or even stop capturing."
+ " device %s", v4l2object->videodev);
+ /* have we de-queued a buffer ? */
+ if (!(buffer.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
+ GST_DEBUG_OBJECT (pool->v4l2elem, "reenqueing buffer");
+ /* FIXME ... should we do something here? */
+ }
+ break;
+ case EINTR:
+ GST_WARNING_OBJECT (pool->v4l2elem,
+ "could not sync on a buffer on device %s", v4l2object->videodev);
+ break;
+ default:
+ GST_WARNING_OBJECT (pool->v4l2elem,
+ "Grabbing frame got interrupted on %s unexpectedly. %d: %s.",
+ v4l2object->videodev, errno, g_strerror (errno));
+ break;
+ }
+
+ return NULL;
+}
+
+/**
+ * gst_v4l2_buffer_pool_available_buffers:
+ * @pool: the pool
+ *
+ * Check the number of buffers available to the driver, ie. buffers that
+ * have been QBUF'd but not yet DQBUF'd.
+ *
+ * Returns: the number of buffers available.
+ */
+gint
+gst_v4l2_buffer_pool_available_buffers (GstV4l2BufferPool * pool)
+{
+ return pool->buffer_count - pool->num_live_buffers;
+}
diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h
new file mode 100644
index 0000000..caad9ac
--- /dev/null
+++ b/sys/v4l2/gstv4l2bufferpool.h
@@ -0,0 +1,97 @@
+/* GStreamer
+ *
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ * 2009 Texas Instruments, Inc - http://www.ti.com/
+ *
+ * gstv4l2bufferpool.h V4L2 buffer pool class
+ *
+ * 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.
+ */
+
+#ifndef __GSTV4L2BUFFER_H__
+#define __GSTV4L2BUFFER_H__
+
+#include <gst/gst.h>
+#include "v4l2_calls.h"
+
+GST_DEBUG_CATEGORY_EXTERN (v4l2buffer_debug);
+
+G_BEGIN_DECLS
+
+
+GType gst_v4l2_buffer_get_type (void);
+#define GST_TYPE_V4L2_BUFFER (gst_v4l2_buffer_get_type())
+#define GST_IS_V4L2_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_BUFFER))
+#define GST_V4L2_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_BUFFER, GstV4l2Buffer))
+
+GType gst_v4l2_buffer_pool_get_type (void);
+#define GST_TYPE_V4L2_BUFFER_POOL (gst_v4l2_buffer_pool_get_type())
+#define GST_IS_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_BUFFER_POOL))
+#define GST_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_BUFFER_POOL, GstV4l2BufferPool))
+
+
+
+typedef struct _GstV4l2BufferPool GstV4l2BufferPool;
+typedef struct _GstV4l2Buffer GstV4l2Buffer;
+
+
+struct _GstV4l2BufferPool
+{
+ GstMiniObject parent;
+
+ GstElement *v4l2elem; /* the v4l2 src/sink that owns us.. maybe we should be owned by v4l2object? */
+ gboolean requeuebuf; /* if true, unusued buffers are automatically re-QBUF'd */
+ enum v4l2_buf_type type; /* V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_OUTPUT */
+
+ GMutex *lock;
+ gboolean running; /* with lock */
+ gint num_live_buffers; /* number of buffers not with driver */
+ GAsyncQueue* avail_buffers;/* pool of available buffers, not with the driver and which aren't held outside the bufferpool */
+ gint video_fd; /* a dup(2) of the v4l2object's video_fd */
+ guint buffer_count;
+ GstV4l2Buffer **buffers;
+};
+
+struct _GstV4l2Buffer {
+ GstBuffer buffer;
+
+ struct v4l2_buffer vbuffer;
+
+ /* FIXME: have GstV4l2Src* instead, as this has GstV4l2BufferPool* */
+ /* FIXME: do we really want to fix this if GstV4l2Buffer/Pool is shared
+ * between v4l2src and v4l2sink??
+ */
+ GstV4l2BufferPool *pool;
+};
+
+void gst_v4l2_buffer_pool_destroy (GstV4l2BufferPool * pool);
+GstV4l2BufferPool *gst_v4l2_buffer_pool_new (GstElement *v4l2elem, gint fd, gint num_buffers, GstCaps * caps, gboolean requeuebuf, enum v4l2_buf_type type);
+
+
+GstV4l2Buffer *gst_v4l2_buffer_pool_get (GstV4l2BufferPool *pool, gboolean blocking);
+gboolean gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool *pool, GstV4l2Buffer *buf);
+GstV4l2Buffer *gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool *pool);
+
+gint gst_v4l2_buffer_pool_available_buffers (GstV4l2BufferPool *pool);
+
+
+#define GST_V4L2_BUFFER_POOL_LOCK(pool) g_mutex_lock ((pool)->lock)
+#define GST_V4L2_BUFFER_POOL_UNLOCK(pool) g_mutex_unlock ((pool)->lock)
+
+G_END_DECLS
+
+#endif /* __GSTV4L2BUFFER_H__ */
diff --git a/sys/v4l2/gstv4l2colorbalance.c b/sys/v4l2/gstv4l2colorbalance.c
new file mode 100644
index 0000000..f5cde09
--- /dev/null
+++ b/sys/v4l2/gstv4l2colorbalance.c
@@ -0,0 +1,106 @@
+/* GStreamer
+ *
+ * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2colorbalance.c: color balance interface implementation for V4L2
+ *
+ * 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 <gst/gst.h>
+#include "gstv4l2colorbalance.h"
+#include "gstv4l2object.h"
+
+GST_BOILERPLATE (GstV4l2ColorBalanceChannel,
+ gst_v4l2_color_balance_channel,
+ GstColorBalanceChannel, GST_TYPE_COLOR_BALANCE_CHANNEL);
+
+static void
+gst_v4l2_color_balance_channel_base_init (gpointer g_class)
+{
+}
+
+static void
+gst_v4l2_color_balance_channel_class_init (GstV4l2ColorBalanceChannelClass *
+ klass)
+{
+}
+
+static void
+gst_v4l2_color_balance_channel_init (GstV4l2ColorBalanceChannel * channel,
+ GstV4l2ColorBalanceChannelClass * klass)
+{
+ channel->id = (guint32) - 1;
+}
+
+static G_GNUC_UNUSED gboolean
+gst_v4l2_color_balance_contains_channel (GstV4l2Object * v4l2object,
+ GstV4l2ColorBalanceChannel * v4l2channel)
+{
+ const GList *item;
+
+ for (item = v4l2object->colors; item != NULL; item = item->next)
+ if (item->data == v4l2channel)
+ return TRUE;
+
+ return FALSE;
+}
+
+const GList *
+gst_v4l2_color_balance_list_channels (GstV4l2Object * v4l2object)
+{
+ return v4l2object->colors;
+}
+
+void
+gst_v4l2_color_balance_set_value (GstV4l2Object * v4l2object,
+ GstColorBalanceChannel * channel, gint value)
+{
+
+ GstV4l2ColorBalanceChannel *v4l2channel =
+ GST_V4L2_COLOR_BALANCE_CHANNEL (channel);
+
+ /* assert that we're opened and that we're using a known item */
+ g_return_if_fail (GST_V4L2_IS_OPEN (v4l2object));
+ g_return_if_fail (gst_v4l2_color_balance_contains_channel (v4l2object,
+ v4l2channel));
+
+ gst_v4l2_set_attribute (v4l2object, v4l2channel->id, value);
+}
+
+gint
+gst_v4l2_color_balance_get_value (GstV4l2Object * v4l2object,
+ GstColorBalanceChannel * channel)
+{
+ GstV4l2ColorBalanceChannel *v4l2channel =
+ GST_V4L2_COLOR_BALANCE_CHANNEL (channel);
+ gint value;
+
+ /* assert that we're opened and that we're using a known item */
+ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), 0);
+ g_return_val_if_fail (gst_v4l2_color_balance_contains_channel (v4l2object,
+ v4l2channel), 0);
+
+ if (!gst_v4l2_get_attribute (v4l2object, v4l2channel->id, &value))
+ return 0;
+
+ return value;
+}
diff --git a/sys/v4l2/gstv4l2colorbalance.h b/sys/v4l2/gstv4l2colorbalance.h
new file mode 100644
index 0000000..9e183f0
--- /dev/null
+++ b/sys/v4l2/gstv4l2colorbalance.h
@@ -0,0 +1,104 @@
+/* GStreamer
+ *
+ * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2colorbalance.h: color balance interface implementation for V4L2
+ *
+ * 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.
+ */
+
+#ifndef __GST_V4L2_COLOR_BALANCE_H__
+#define __GST_V4L2_COLOR_BALANCE_H__
+
+#include <gst/gst.h>
+#include <gst/interfaces/colorbalance.h>
+#include "v4l2_calls.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL \
+ (gst_v4l2_color_balance_channel_get_type ())
+#define GST_V4L2_COLOR_BALANCE_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, \
+ GstV4l2ColorBalanceChannel))
+#define GST_V4L2_COLOR_BALANCE_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, \
+ GstV4l2ColorBalanceChannelClass))
+#define GST_IS_V4L2_COLOR_BALANCE_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL))
+#define GST_IS_V4L2_COLOR_BALANCE_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL))
+
+typedef struct _GstV4l2ColorBalanceChannel {
+ GstColorBalanceChannel parent;
+
+ guint32 id;
+} GstV4l2ColorBalanceChannel;
+
+typedef struct _GstV4l2ColorBalanceChannelClass {
+ GstColorBalanceChannelClass parent;
+} GstV4l2ColorBalanceChannelClass;
+
+GType gst_v4l2_color_balance_channel_get_type (void);
+
+const GList * gst_v4l2_color_balance_list_channels (GstV4l2Object * v4l2object);
+
+void gst_v4l2_color_balance_set_value (GstV4l2Object * v4l2object,
+ GstColorBalanceChannel * channel,
+ gint value);
+
+gint gst_v4l2_color_balance_get_value (GstV4l2Object * v4l2object,
+ GstColorBalanceChannel * channel);
+
+#define GST_IMPLEMENT_V4L2_COLOR_BALANCE_METHODS(Type, interface_as_function) \
+ \
+static const GList * \
+interface_as_function ## _color_balance_list_channels (GstColorBalance * balance) \
+{ \
+ Type *this = (Type*) balance; \
+ return gst_v4l2_color_balance_list_channels(this->v4l2object); \
+} \
+ \
+static void \
+interface_as_function ## _color_balance_set_value (GstColorBalance * balance, \
+ GstColorBalanceChannel * channel, \
+ gint value) \
+{ \
+ Type *this = (Type*) balance; \
+ gst_v4l2_color_balance_set_value(this->v4l2object, channel, value); \
+} \
+ \
+static gint \
+interface_as_function ## _color_balance_get_value (GstColorBalance * balance, \
+ GstColorBalanceChannel * channel) \
+{ \
+ Type *this = (Type*) balance; \
+ return gst_v4l2_color_balance_get_value(this->v4l2object, channel); \
+} \
+ \
+static void \
+interface_as_function ## _color_balance_interface_init (GstColorBalanceClass * klass) \
+{ \
+ GST_COLOR_BALANCE_TYPE (klass) = GST_COLOR_BALANCE_HARDWARE; \
+ \
+ /* default virtual functions */ \
+ klass->list_channels = interface_as_function ## _color_balance_list_channels; \
+ klass->set_value = interface_as_function ## _color_balance_set_value; \
+ klass->get_value = interface_as_function ## _color_balance_get_value; \
+} \
+
+#endif /* __GST_V4L2_COLOR_BALANCE_H__ */
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
new file mode 100644
index 0000000..81d1cb7
--- /dev/null
+++ b/sys/v4l2/gstv4l2object.c
@@ -0,0 +1,2247 @@
+/* GStreamer
+ *
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2object.c: base class for V4L2 elements
+ *
+ * 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 <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifdef HAVE_GUDEV
+#include <gudev/gudev.h>
+#endif
+
+#include "v4l2_calls.h"
+#include "gstv4l2tuner.h"
+#ifdef HAVE_XVIDEO
+#include "gstv4l2xoverlay.h"
+#endif
+#include "gstv4l2colorbalance.h"
+
+#include "gst/gst-i18n-plugin.h"
+
+/* videodev2.h is not versioned and we can't easily check for the presence
+ * of enum values at compile time, but the V4L2_CAP_VIDEO_OUTPUT_OVERLAY define
+ * was added in the same commit as V4L2_FIELD_INTERLACED_{TB,BT} (b2787845) */
+#ifndef V4L2_CAP_VIDEO_OUTPUT_OVERLAY
+#define V4L2_FIELD_INTERLACED_TB 8
+#define V4L2_FIELD_INTERLACED_BT 9
+#endif
+
+GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
+#define GST_CAT_DEFAULT v4l2_debug
+
+
+#define DEFAULT_PROP_DEVICE_NAME NULL
+#define DEFAULT_PROP_DEVICE_FD -1
+#define DEFAULT_PROP_FLAGS 0
+#define DEFAULT_PROP_TV_NORM 0
+#define DEFAULT_PROP_CHANNEL NULL
+#define DEFAULT_PROP_FREQUENCY 0
+
+enum
+{
+ PROP_0,
+ V4L2_STD_OBJECT_PROPS,
+};
+
+G_LOCK_DEFINE_STATIC (probe_lock);
+
+const GList *
+gst_v4l2_probe_get_properties (GstPropertyProbe * probe)
+{
+ GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
+ static GList *list = NULL;
+
+ /* well, not perfect, but better than no locking at all.
+ * In the worst case we leak a list node, so who cares? */
+ G_LOCK (probe_lock);
+
+ if (!list) {
+ list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
+ }
+
+ G_UNLOCK (probe_lock);
+
+ return list;
+}
+
+static gboolean init = FALSE;
+static GList *devices = NULL;
+
+#ifdef HAVE_GUDEV
+static gboolean
+gst_v4l2_class_probe_devices_with_udev (GstElementClass * klass, gboolean check,
+ GList ** klass_devices)
+{
+ GUdevClient *client = NULL;
+ GList *item;
+
+ if (!check) {
+ while (devices) {
+ gchar *device = devices->data;
+ devices = g_list_remove (devices, device);
+ g_free (device);
+ }
+
+ GST_INFO ("Enumerating video4linux devices from udev");
+ client = g_udev_client_new (NULL);
+ if (!client) {
+ GST_WARNING ("Failed to initialize gudev client");
+ goto finish;
+ }
+
+ item = g_udev_client_query_by_subsystem (client, "video4linux");
+ while (item) {
+ GUdevDevice *device = item->data;
+ gchar *devnode = g_strdup (g_udev_device_get_device_file (device));
+ gint api = g_udev_device_get_property_as_int (device, "ID_V4L_VERSION");
+ GST_INFO ("Found new device: %s, API: %d", devnode, api);
+ /* Append v4l2 devices only. If api is 0 probably v4l_id has
+ been stripped out of the current udev installation, append
+ anyway */
+ if (api == 0) {
+ GST_WARNING
+ ("Couldn't retrieve ID_V4L_VERSION, silly udev installation?");
+ }
+ if ((api == 2 || api == 0)) {
+ devices = g_list_append (devices, devnode);
+ } else {
+ g_free (devnode);
+ }
+ g_object_unref (device);
+ item = item->next;
+ }
+ g_list_free (item);
+ init = TRUE;
+ }
+
+finish:
+ if (client) {
+ g_object_unref (client);
+ }
+
+ *klass_devices = devices;
+
+ return init;
+}
+#endif /* HAVE_GUDEV */
+
+static gboolean
+gst_v4l2_class_probe_devices (GstElementClass * klass, gboolean check,
+ GList ** klass_devices)
+{
+ if (!check) {
+ const gchar *dev_base[] = { "/dev/video", "/dev/v4l2/video", NULL };
+ gint base, n, fd;
+
+ while (devices) {
+ gchar *device = devices->data;
+ devices = g_list_remove (devices, device);
+ g_free (device);
+ }
+
+ /*
+ * detect /dev entries
+ */
+ for (n = 0; n < 64; n++) {
+ for (base = 0; dev_base[base] != NULL; base++) {
+ struct stat s;
+ gchar *device = g_strdup_printf ("%s%d",
+ dev_base[base],
+ n);
+
+ /*
+ * does the /dev/ entry exist at all?
+ */
+ if (stat (device, &s) == 0) {
+ /*
+ * yes: is a device attached?
+ */
+ if (S_ISCHR (s.st_mode)) {
+
+ if ((fd = open (device, O_RDWR | O_NONBLOCK)) > 0 || errno == EBUSY) {
+ if (fd > 0)
+ close (fd);
+
+ devices = g_list_append (devices, device);
+ break;
+ }
+ }
+ }
+ g_free (device);
+ }
+ }
+ init = TRUE;
+ }
+
+ *klass_devices = devices;
+
+ return init;
+}
+
+void
+gst_v4l2_probe_probe_property (GstPropertyProbe * probe,
+ guint prop_id, const GParamSpec * pspec, GList ** klass_devices)
+{
+ GstElementClass *klass = GST_ELEMENT_GET_CLASS (probe);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+#ifdef HAVE_GUDEV
+ if (!gst_v4l2_class_probe_devices_with_udev (klass, FALSE, klass_devices))
+ gst_v4l2_class_probe_devices (klass, FALSE, klass_devices);
+#else /* !HAVE_GUDEV */
+ gst_v4l2_class_probe_devices (klass, FALSE, klass_devices);
+#endif /* HAVE_GUDEV */
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
+ break;
+ }
+}
+
+gboolean
+gst_v4l2_probe_needs_probe (GstPropertyProbe * probe,
+ guint prop_id, const GParamSpec * pspec, GList ** klass_devices)
+{
+ GstElementClass *klass = GST_ELEMENT_GET_CLASS (probe);
+ gboolean ret = FALSE;
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+#ifdef HAVE_GUDEV
+ ret =
+ !gst_v4l2_class_probe_devices_with_udev (klass, FALSE, klass_devices);
+#else /* !HAVE_GUDEV */
+ ret = !gst_v4l2_class_probe_devices (klass, TRUE, klass_devices);
+#endif /* HAVE_GUDEV */
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
+ break;
+ }
+ return ret;
+}
+
+static GValueArray *
+gst_v4l2_class_list_devices (GstElementClass * klass, GList ** klass_devices)
+{
+ GValueArray *array;
+ GValue value = { 0 };
+ GList *item;
+
+ if (!*klass_devices)
+ return NULL;
+
+ array = g_value_array_new (g_list_length (*klass_devices));
+ item = *klass_devices;
+ g_value_init (&value, G_TYPE_STRING);
+ while (item) {
+ gchar *device = item->data;
+
+ g_value_set_string (&value, device);
+ g_value_array_append (array, &value);
+
+ item = item->next;
+ }
+ g_value_unset (&value);
+
+ return array;
+}
+
+GValueArray *
+gst_v4l2_probe_get_values (GstPropertyProbe * probe,
+ guint prop_id, const GParamSpec * pspec, GList ** klass_devices)
+{
+ GstElementClass *klass = GST_ELEMENT_GET_CLASS (probe);
+ GValueArray *array = NULL;
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ array = gst_v4l2_class_list_devices (klass, klass_devices);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
+ break;
+ }
+
+ return array;
+}
+
+#define GST_TYPE_V4L2_DEVICE_FLAGS (gst_v4l2_device_get_type ())
+static GType
+gst_v4l2_device_get_type (void)
+{
+ static GType v4l2_device_type = 0;
+
+ if (v4l2_device_type == 0) {
+ static const GFlagsValue values[] = {
+ {V4L2_CAP_VIDEO_CAPTURE, "Device supports video capture", "capture"},
+ {V4L2_CAP_VIDEO_OUTPUT, "Device supports video playback", "output"},
+ {V4L2_CAP_VIDEO_OVERLAY, "Device supports video overlay", "overlay"},
+
+ {V4L2_CAP_VBI_CAPTURE, "Device supports the VBI capture", "vbi-capture"},
+ {V4L2_CAP_VBI_OUTPUT, "Device supports the VBI output", "vbi-output"},
+
+ {V4L2_CAP_TUNER, "Device has a tuner or modulator", "tuner"},
+ {V4L2_CAP_AUDIO, "Device has audio inputs or outputs", "audio"},
+
+ {0, NULL, NULL}
+ };
+
+ v4l2_device_type =
+ g_flags_register_static ("GstV4l2DeviceTypeFlags", values);
+ }
+
+ return v4l2_device_type;
+}
+
+#define GST_TYPE_V4L2_TV_NORM (gst_v4l2_tv_norm_get_type ())
+static GType
+gst_v4l2_tv_norm_get_type (void)
+{
+ static GType v4l2_tv_norm = 0;
+
+ if (!v4l2_tv_norm) {
+ static const GEnumValue tv_norms[] = {
+ {0, "none", "none"},
+
+ {V4L2_STD_NTSC, "NTSC", "NTSC"},
+ {V4L2_STD_NTSC_M, "NTSC-M", "NTSC-M"},
+ {V4L2_STD_NTSC_M_JP, "NTSC-M-JP", "NTSC-M-JP"},
+ {V4L2_STD_NTSC_M_KR, "NTSC-M-KR", "NTSC-M-KR"},
+ {V4L2_STD_NTSC_443, "NTSC-443", "NTSC-443"},
+
+ {V4L2_STD_PAL, "PAL", "PAL"},
+ {V4L2_STD_PAL_BG, "PAL-BG", "PAL-BG"},
+ {V4L2_STD_PAL_B, "PAL-B", "PAL-B"},
+ {V4L2_STD_PAL_B1, "PAL-B1", "PAL-B1"},
+ {V4L2_STD_PAL_G, "PAL-G", "PAL-G"},
+ {V4L2_STD_PAL_H, "PAL-H", "PAL-H"},
+ {V4L2_STD_PAL_I, "PAL-I", "PAL-I"},
+ {V4L2_STD_PAL_DK, "PAL-DK", "PAL-DK"},
+ {V4L2_STD_PAL_D, "PAL-D", "PAL-D"},
+ {V4L2_STD_PAL_D1, "PAL-D1", "PAL-D1"},
+ {V4L2_STD_PAL_K, "PAL-K", "PAL-K"},
+ {V4L2_STD_PAL_M, "PAL-M", "PAL-M"},
+ {V4L2_STD_PAL_N, "PAL-N", "PAL-N"},
+ {V4L2_STD_PAL_Nc, "PAL-Nc", "PAL-Nc"},
+ {V4L2_STD_PAL_60, "PAL-60", "PAL-60"},
+
+ {V4L2_STD_SECAM, "SECAM", "SECAM"},
+ {V4L2_STD_SECAM_B, "SECAM-B", "SECAM-B"},
+ {V4L2_STD_SECAM_G, "SECAM-G", "SECAM-G"},
+ {V4L2_STD_SECAM_H, "SECAM-H", "SECAM-H"},
+ {V4L2_STD_SECAM_DK, "SECAM-DK", "SECAM-DK"},
+ {V4L2_STD_SECAM_D, "SECAM-D", "SECAM-D"},
+ {V4L2_STD_SECAM_K, "SECAM-K", "SECAM-K"},
+ {V4L2_STD_SECAM_K1, "SECAM-K1", "SECAM-K1"},
+ {V4L2_STD_SECAM_L, "SECAM-L", "SECAM-L"},
+ {V4L2_STD_SECAM_LC, "SECAM-Lc", "SECAM-Lc"},
+
+ {0, NULL, NULL}
+ };
+
+ v4l2_tv_norm = g_enum_register_static ("V4L2_TV_norms", tv_norms);
+ }
+
+ return v4l2_tv_norm;
+}
+
+void
+gst_v4l2_object_install_properties_helper (GObjectClass * gobject_class,
+ const char *default_device)
+{
+ g_object_class_install_property (gobject_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device", "Device location",
+ default_device, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
+ g_param_spec_string ("device-name", "Device name",
+ "Name of the device", DEFAULT_PROP_DEVICE_NAME,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_DEVICE_FD,
+ g_param_spec_int ("device-fd", "File descriptor",
+ "File descriptor of the device", -1, G_MAXINT, DEFAULT_PROP_DEVICE_FD,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_FLAGS,
+ g_param_spec_flags ("flags", "Flags", "Device type flags",
+ GST_TYPE_V4L2_DEVICE_FLAGS, DEFAULT_PROP_FLAGS,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GstV4l2Src:brightness
+ *
+ * Picture brightness, or more precisely, the black level
+ *
+ * Since: 0.10.26
+ */
+ g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
+ g_param_spec_int ("brightness", "Brightness",
+ "Picture brightness, or more precisely, the black level", G_MININT,
+ G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
+ /**
+ * GstV4l2Src:contrast
+ *
+ * Picture contrast or luma gain
+ *
+ * Since: 0.10.26
+ */
+ g_object_class_install_property (gobject_class, PROP_CONTRAST,
+ g_param_spec_int ("contrast", "Contrast",
+ "Picture contrast or luma gain", G_MININT,
+ G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
+ /**
+ * GstV4l2Src:saturation
+ *
+ * Picture color saturation or chroma gain
+ *
+ * Since: 0.10.26
+ */
+ g_object_class_install_property (gobject_class, PROP_SATURATION,
+ g_param_spec_int ("saturation", "Saturation",
+ "Picture color saturation or chroma gain", G_MININT,
+ G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
+ /**
+ * GstV4l2Src:hue
+ *
+ * Hue or color balance
+ *
+ * Since: 0.10.26
+ */
+ g_object_class_install_property (gobject_class, PROP_HUE,
+ g_param_spec_int ("hue", "Hue",
+ "Hue or color balance", G_MININT,
+ G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
+
+ /**
+ * GstV4l2Src:norm
+ *
+ * TV norm
+ *
+ * Since: 0.10.31
+ */
+ g_object_class_install_property (gobject_class, PROP_TV_NORM,
+ g_param_spec_enum ("norm", "TV norm",
+ "video standard",
+ GST_TYPE_V4L2_TV_NORM, DEFAULT_PROP_TV_NORM,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+GstV4l2Object *
+gst_v4l2_object_new (GstElement * element,
+ enum v4l2_buf_type type,
+ const char *default_device,
+ GstV4l2GetInOutFunction get_in_out_func,
+ GstV4l2SetInOutFunction set_in_out_func,
+ GstV4l2UpdateFpsFunction update_fps_func)
+{
+ GstV4l2Object *v4l2object;
+
+ /*
+ * some default values
+ */
+ v4l2object = g_new0 (GstV4l2Object, 1);
+
+ v4l2object->type = type;
+ v4l2object->formats = NULL;
+
+ v4l2object->element = element;
+ v4l2object->get_in_out_func = get_in_out_func;
+ v4l2object->set_in_out_func = set_in_out_func;
+ v4l2object->update_fps_func = update_fps_func;
+
+ v4l2object->video_fd = -1;
+ v4l2object->poll = gst_poll_new (TRUE);
+ v4l2object->buffer = NULL;
+ v4l2object->videodev = g_strdup (default_device);
+
+ v4l2object->norms = NULL;
+ v4l2object->channels = NULL;
+ v4l2object->colors = NULL;
+
+ v4l2object->xwindow_id = 0;
+
+ return v4l2object;
+}
+
+static gboolean gst_v4l2_object_clear_format_list (GstV4l2Object * v4l2object);
+
+
+void
+gst_v4l2_object_destroy (GstV4l2Object * v4l2object)
+{
+ g_return_if_fail (v4l2object != NULL);
+
+ if (v4l2object->videodev)
+ g_free (v4l2object->videodev);
+
+ if (v4l2object->poll)
+ gst_poll_free (v4l2object->poll);
+
+ if (v4l2object->channel)
+ g_free (v4l2object->channel);
+
+ if (v4l2object->formats) {
+ gst_v4l2_object_clear_format_list (v4l2object);
+ }
+
+ g_free (v4l2object);
+}
+
+
+static gboolean
+gst_v4l2_object_clear_format_list (GstV4l2Object * v4l2object)
+{
+ g_slist_foreach (v4l2object->formats, (GFunc) g_free, NULL);
+ g_slist_free (v4l2object->formats);
+ v4l2object->formats = NULL;
+
+ return TRUE;
+}
+
+static gint
+gst_v4l2_object_prop_to_cid (guint prop_id)
+{
+ gint cid = -1;
+
+ switch (prop_id) {
+ case PROP_BRIGHTNESS:
+ cid = V4L2_CID_BRIGHTNESS;
+ break;
+ case PROP_CONTRAST:
+ cid = V4L2_CID_CONTRAST;
+ break;
+ case PROP_SATURATION:
+ cid = V4L2_CID_SATURATION;
+ break;
+ case PROP_HUE:
+ cid = V4L2_CID_HUE;
+ break;
+ default:
+ GST_WARNING ("unmapped property id: %d", prop_id);
+ }
+ return cid;
+}
+
+
+gboolean
+gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
+ guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_free (v4l2object->videodev);
+ v4l2object->videodev = g_value_dup_string (value);
+ break;
+ case PROP_BRIGHTNESS:
+ case PROP_CONTRAST:
+ case PROP_SATURATION:
+ case PROP_HUE:
+ {
+ gint cid = gst_v4l2_object_prop_to_cid (prop_id);
+
+ if (cid != -1) {
+ if (GST_V4L2_IS_OPEN (v4l2object)) {
+ gst_v4l2_set_attribute (v4l2object, cid, g_value_get_int (value));
+ }
+ }
+ return TRUE;
+ }
+ break;
+ case PROP_TV_NORM:
+ v4l2object->tv_norm = g_value_get_enum (value);
+ break;
+#if 0
+ case PROP_CHANNEL:
+ if (GST_V4L2_IS_OPEN (v4l2object)) {
+ GstTuner *tuner = GST_TUNER (v4l2object->element);
+ GstTunerChannel *channel = gst_tuner_find_channel_by_name (tuner,
+ (gchar *) g_value_get_string (value));
+
+ if (channel) {
+ /* like gst_tuner_set_channel (tuner, channel)
+ without g_object_notify */
+ gst_v4l2_tuner_set_channel (v4l2object, channel);
+ }
+ } else {
+ g_free (v4l2object->channel);
+ v4l2object->channel = g_value_dup_string (value);
+ }
+ break;
+ case PROP_FREQUENCY:
+ if (GST_V4L2_IS_OPEN (v4l2object)) {
+ GstTuner *tuner = GST_TUNER (v4l2object->element);
+ GstTunerChannel *channel = gst_tuner_get_channel (tuner);
+
+ if (channel &&
+ GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
+ /* like
+ gst_tuner_set_frequency (tuner, channel, g_value_get_ulong (value))
+ without g_object_notify */
+ gst_v4l2_tuner_set_frequency (v4l2object, channel,
+ g_value_get_ulong (value));
+ }
+ } else {
+ v4l2object->frequency = g_value_get_ulong (value);
+ }
+ break;
+#endif
+ default:
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+
+gboolean
+gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_value_set_string (value, v4l2object->videodev);
+ break;
+ case PROP_DEVICE_NAME:
+ {
+ const guchar *new = NULL;
+
+ if (GST_V4L2_IS_OPEN (v4l2object)) {
+ new = v4l2object->vcap.card;
+ } else if (gst_v4l2_open (v4l2object)) {
+ new = v4l2object->vcap.card;
+ gst_v4l2_close (v4l2object);
+ }
+ g_value_set_string (value, (gchar *) new);
+ break;
+ }
+ case PROP_DEVICE_FD:
+ {
+ if (GST_V4L2_IS_OPEN (v4l2object))
+ g_value_set_int (value, v4l2object->video_fd);
+ else
+ g_value_set_int (value, DEFAULT_PROP_DEVICE_FD);
+ break;
+ }
+ case PROP_FLAGS:
+ {
+ guint flags = 0;
+
+ if (GST_V4L2_IS_OPEN (v4l2object)) {
+ flags |= v4l2object->vcap.capabilities &
+ (V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_VIDEO_OUTPUT |
+ V4L2_CAP_VIDEO_OVERLAY |
+ V4L2_CAP_VBI_CAPTURE |
+ V4L2_CAP_VBI_OUTPUT | V4L2_CAP_TUNER | V4L2_CAP_AUDIO);
+ }
+ g_value_set_flags (value, flags);
+ break;
+ }
+ case PROP_BRIGHTNESS:
+ case PROP_CONTRAST:
+ case PROP_SATURATION:
+ case PROP_HUE:
+ {
+ gint cid = gst_v4l2_object_prop_to_cid (prop_id);
+
+ if (cid != -1) {
+ if (GST_V4L2_IS_OPEN (v4l2object)) {
+ gint v;
+ if (gst_v4l2_get_attribute (v4l2object, cid, &v)) {
+ g_value_set_int (value, v);
+ }
+ }
+ }
+ return TRUE;
+ }
+ break;
+ case PROP_TV_NORM:
+ g_value_set_enum (value, v4l2object->tv_norm);
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+static void
+gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
+{
+ GstTunerNorm *norm = NULL;
+ GstTunerChannel *channel = NULL;
+ GstTuner *tuner;
+
+ if (!GST_IS_TUNER (v4l2object->element))
+ return;
+
+ tuner = GST_TUNER (v4l2object->element);
+
+ if (v4l2object->tv_norm)
+ norm = gst_v4l2_tuner_get_norm_by_std_id (v4l2object, v4l2object->tv_norm);
+ GST_DEBUG_OBJECT (v4l2object->element, "tv_norm=0x%" G_GINT64_MODIFIER "x, "
+ "norm=%p", (guint64) v4l2object->tv_norm, norm);
+ if (norm) {
+ gst_tuner_set_norm (tuner, norm);
+ } else {
+ norm =
+ GST_TUNER_NORM (gst_tuner_get_norm (GST_TUNER (v4l2object->element)));
+ if (norm) {
+ v4l2object->tv_norm =
+ gst_v4l2_tuner_get_std_id_by_norm (v4l2object, norm);
+ gst_tuner_norm_changed (tuner, norm);
+ }
+ }
+
+ if (v4l2object->channel)
+ channel = gst_tuner_find_channel_by_name (tuner, v4l2object->channel);
+ if (channel) {
+ gst_tuner_set_channel (tuner, channel);
+ } else {
+ channel =
+ GST_TUNER_CHANNEL (gst_tuner_get_channel (GST_TUNER
+ (v4l2object->element)));
+ if (channel) {
+ g_free (v4l2object->channel);
+ v4l2object->channel = g_strdup (channel->label);
+ gst_tuner_channel_changed (tuner, channel);
+ }
+ }
+
+ if (channel
+ && GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
+ if (v4l2object->frequency != 0) {
+ gst_tuner_set_frequency (tuner, channel, v4l2object->frequency);
+ } else {
+ v4l2object->frequency = gst_tuner_get_frequency (tuner, channel);
+ if (v4l2object->frequency == 0) {
+ /* guess */
+ gst_tuner_set_frequency (tuner, channel, 1000);
+ } else {
+ }
+ }
+ }
+}
+
+gboolean
+gst_v4l2_object_start (GstV4l2Object * v4l2object)
+{
+ if (gst_v4l2_open (v4l2object))
+ gst_v4l2_set_defaults (v4l2object);
+ else
+ return FALSE;
+
+#ifdef HAVE_XVIDEO
+ gst_v4l2_xoverlay_start (v4l2object);
+#endif
+
+ return TRUE;
+}
+
+gboolean
+gst_v4l2_object_stop (GstV4l2Object * v4l2object)
+{
+#ifdef HAVE_XVIDEO
+ gst_v4l2_xoverlay_stop (v4l2object);
+#endif
+
+ if (!gst_v4l2_close (v4l2object))
+ return FALSE;
+
+ if (v4l2object->formats) {
+ gst_v4l2_object_clear_format_list (v4l2object);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * common format / caps utilities:
+ */
+typedef struct
+{
+ guint32 format;
+ gboolean dimensions;
+} GstV4L2FormatDesc;
+
+static const GstV4L2FormatDesc gst_v4l2_formats[] = {
+ /* from Linux 2.6.15 videodev2.h */
+ {V4L2_PIX_FMT_RGB332, TRUE},
+ {V4L2_PIX_FMT_RGB555, TRUE},
+ {V4L2_PIX_FMT_RGB565, TRUE},
+ {V4L2_PIX_FMT_RGB555X, TRUE},
+ {V4L2_PIX_FMT_RGB565X, TRUE},
+ {V4L2_PIX_FMT_BGR24, TRUE},
+ {V4L2_PIX_FMT_RGB24, TRUE},
+ {V4L2_PIX_FMT_BGR32, TRUE},
+ {V4L2_PIX_FMT_RGB32, TRUE},
+ {V4L2_PIX_FMT_GREY, TRUE},
+ {V4L2_PIX_FMT_YVU410, TRUE},
+ {V4L2_PIX_FMT_YVU420, TRUE},
+ {V4L2_PIX_FMT_YUYV, TRUE},
+ {V4L2_PIX_FMT_UYVY, TRUE},
+ {V4L2_PIX_FMT_YUV422P, TRUE},
+ {V4L2_PIX_FMT_YUV411P, TRUE},
+ {V4L2_PIX_FMT_Y41P, TRUE},
+
+ /* two planes -- one Y, one Cr + Cb interleaved */
+ {V4L2_PIX_FMT_NV12, TRUE},
+ {V4L2_PIX_FMT_NV21, TRUE},
+
+ /* The following formats are not defined in the V4L2 specification */
+ {V4L2_PIX_FMT_YUV410, TRUE},
+ {V4L2_PIX_FMT_YUV420, TRUE},
+ {V4L2_PIX_FMT_YYUV, TRUE},
+ {V4L2_PIX_FMT_HI240, TRUE},
+
+ /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
+#ifdef V4L2_PIX_FMT_SBGGR8
+ {V4L2_PIX_FMT_SBGGR8, TRUE},
+#endif
+
+ /* compressed formats */
+ {V4L2_PIX_FMT_MJPEG, TRUE},
+ {V4L2_PIX_FMT_JPEG, TRUE},
+#ifdef V4L2_PIX_FMT_PJPG
+ {V4L2_PIX_FMT_PJPG, TRUE},
+#endif
+ {V4L2_PIX_FMT_DV, TRUE},
+ {V4L2_PIX_FMT_MPEG, FALSE},
+
+ /* Vendor-specific formats */
+ {V4L2_PIX_FMT_WNVA, TRUE},
+
+#ifdef V4L2_PIX_FMT_SN9C10X
+ {V4L2_PIX_FMT_SN9C10X, TRUE},
+#endif
+#ifdef V4L2_PIX_FMT_PWC1
+ {V4L2_PIX_FMT_PWC1, TRUE},
+#endif
+#ifdef V4L2_PIX_FMT_PWC2
+ {V4L2_PIX_FMT_PWC2, TRUE},
+#endif
+#ifdef V4L2_PIX_FMT_YVYU
+ {V4L2_PIX_FMT_YVYU, TRUE},
+#endif
+};
+
+#define GST_V4L2_FORMAT_COUNT (G_N_ELEMENTS (gst_v4l2_formats))
+
+
+static struct v4l2_fmtdesc *
+gst_v4l2_object_get_format_from_fourcc (GstV4l2Object * v4l2object,
+ guint32 fourcc)
+{
+ struct v4l2_fmtdesc *fmt;
+ GSList *walk;
+
+ if (fourcc == 0)
+ return NULL;
+
+ walk = gst_v4l2_object_get_format_list (v4l2object);
+ while (walk) {
+ fmt = (struct v4l2_fmtdesc *) walk->data;
+ if (fmt->pixelformat == fourcc)
+ return fmt;
+ /* special case for jpeg */
+ if (fmt->pixelformat == V4L2_PIX_FMT_MJPEG ||
+ fmt->pixelformat == V4L2_PIX_FMT_JPEG
+#ifdef V4L2_PIX_FMT_PJPG
+ || fmt->pixelformat == V4L2_PIX_FMT_PJPG
+#endif
+ ) {
+ if (fourcc == V4L2_PIX_FMT_JPEG || fourcc == V4L2_PIX_FMT_MJPEG
+#ifdef V4L2_PIX_FMT_PJPG
+ || fourcc == V4L2_PIX_FMT_PJPG
+#endif
+ ) {
+ return fmt;
+ }
+ }
+ walk = g_slist_next (walk);
+ }
+
+ return NULL;
+}
+
+
+
+/* complete made up ranking, the values themselves are meaningless */
+/* These ranks MUST be X such that X<<15 fits on a signed int - see
+ the comment at the end of gst_v4l2_object_format_get_rank. */
+#define YUV_BASE_RANK 1000
+#define JPEG_BASE_RANK 500
+#define DV_BASE_RANK 200
+#define RGB_BASE_RANK 100
+#define YUV_ODD_BASE_RANK 50
+#define RGB_ODD_BASE_RANK 25
+#define BAYER_BASE_RANK 15
+#define S910_BASE_RANK 10
+#define GREY_BASE_RANK 5
+#define PWC_BASE_RANK 1
+
+/* This flag is already used by libv4l2 although
+ * it was added to the Linux kernel in 2.6.32
+ */
+#ifndef V4L2_FMT_FLAG_EMULATED
+#define V4L2_FMT_FLAG_EMULATED 0x0002
+#endif
+
+static gint
+gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
+{
+ guint32 fourcc = fmt->pixelformat;
+ gboolean emulated = ((fmt->flags & V4L2_FMT_FLAG_EMULATED) != 0);
+ gint rank = 0;
+
+ switch (fourcc) {
+ case V4L2_PIX_FMT_MJPEG:
+#ifdef V4L2_PIX_FMT_PJPG
+ case V4L2_PIX_FMT_PJPG:
+ rank = JPEG_BASE_RANK;
+ break;
+#endif
+ case V4L2_PIX_FMT_JPEG:
+ rank = JPEG_BASE_RANK + 1;
+ break;
+ case V4L2_PIX_FMT_MPEG: /* MPEG */
+ rank = JPEG_BASE_RANK + 2;
+ break;
+
+ case V4L2_PIX_FMT_RGB332:
+ case V4L2_PIX_FMT_RGB555:
+ case V4L2_PIX_FMT_RGB555X:
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_RGB565X:
+ rank = RGB_ODD_BASE_RANK;
+ break;
+
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ rank = RGB_BASE_RANK - 1;
+ break;
+
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_BGR32:
+ rank = RGB_BASE_RANK;
+ break;
+
+ case V4L2_PIX_FMT_GREY: /* 8 Greyscale */
+ rank = GREY_BASE_RANK;
+ break;
+
+ case V4L2_PIX_FMT_NV12: /* 12 Y/CbCr 4:2:0 */
+ case V4L2_PIX_FMT_NV21: /* 12 Y/CrCb 4:2:0 */
+ case V4L2_PIX_FMT_YYUV: /* 16 YUV 4:2:2 */
+ case V4L2_PIX_FMT_HI240: /* 8 8-bit color */
+ rank = YUV_ODD_BASE_RANK;
+ break;
+
+ case V4L2_PIX_FMT_YVU410: /* YVU9, 9 bits per pixel */
+ rank = YUV_BASE_RANK + 3;
+ break;
+ case V4L2_PIX_FMT_YUV410: /* YUV9, 9 bits per pixel */
+ rank = YUV_BASE_RANK + 2;
+ break;
+ case V4L2_PIX_FMT_YUV420: /* I420, 12 bits per pixel */
+ rank = YUV_BASE_RANK + 7;
+ break;
+ case V4L2_PIX_FMT_YUYV: /* YUY2, 16 bits per pixel */
+ rank = YUV_BASE_RANK + 10;
+ break;
+ case V4L2_PIX_FMT_YVU420: /* YV12, 12 bits per pixel */
+ rank = YUV_BASE_RANK + 6;
+ break;
+ case V4L2_PIX_FMT_UYVY: /* UYVY, 16 bits per pixel */
+ rank = YUV_BASE_RANK + 9;
+ break;
+ case V4L2_PIX_FMT_Y41P: /* Y41P, 12 bits per pixel */
+ rank = YUV_BASE_RANK + 5;
+ break;
+ case V4L2_PIX_FMT_YUV411P: /* Y41B, 12 bits per pixel */
+ rank = YUV_BASE_RANK + 4;
+ break;
+ case V4L2_PIX_FMT_YUV422P: /* Y42B, 16 bits per pixel */
+ rank = YUV_BASE_RANK + 8;
+ break;
+
+ case V4L2_PIX_FMT_DV:
+ rank = DV_BASE_RANK;
+ break;
+
+ case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */
+ rank = 0;
+ break;
+
+#ifdef V4L2_PIX_FMT_SBGGR8
+ case V4L2_PIX_FMT_SBGGR8:
+ rank = BAYER_BASE_RANK;
+ break;
+#endif
+
+#ifdef V4L2_PIX_FMT_SN9C10X
+ case V4L2_PIX_FMT_SN9C10X:
+ rank = S910_BASE_RANK;
+ break;
+#endif
+
+#ifdef V4L2_PIX_FMT_PWC1
+ case V4L2_PIX_FMT_PWC1:
+ rank = PWC_BASE_RANK;
+ break;
+#endif
+#ifdef V4L2_PIX_FMT_PWC2
+ case V4L2_PIX_FMT_PWC2:
+ rank = PWC_BASE_RANK;
+ break;
+#endif
+
+ default:
+ rank = 0;
+ break;
+ }
+
+ /* All ranks are below 1<<15 so a shift by 15
+ * will a) make all non-emulated formats larger
+ * than emulated and b) will not overflow
+ */
+ if (!emulated)
+ rank <<= 15;
+
+ return rank;
+}
+
+
+
+static gint
+format_cmp_func (gconstpointer a, gconstpointer b)
+{
+ const struct v4l2_fmtdesc *fa = a;
+ const struct v4l2_fmtdesc *fb = b;
+
+ if (fa->pixelformat == fb->pixelformat)
+ return 0;
+
+ return gst_v4l2_object_format_get_rank (fb) -
+ gst_v4l2_object_format_get_rank (fa);
+}
+
+/******************************************************
+ * gst_v4l2_object_fill_format_list():
+ * create list of supported capture formats
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+static gboolean
+gst_v4l2_object_fill_format_list (GstV4l2Object * v4l2object)
+{
+ gint n;
+ struct v4l2_fmtdesc *format;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "getting src format enumerations");
+
+ /* format enumeration */
+ for (n = 0;; n++) {
+ format = g_new0 (struct v4l2_fmtdesc, 1);
+
+ format->index = n;
+ format->type = v4l2object->type;
+
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
+ if (errno == EINVAL) {
+ g_free (format);
+ break; /* end of enumeration */
+ } else {
+ goto failed;
+ }
+ }
+
+ GST_LOG_OBJECT (v4l2object->element, "index: %u", format->index);
+ GST_LOG_OBJECT (v4l2object->element, "type: %d", format->type);
+ GST_LOG_OBJECT (v4l2object->element, "flags: %08x", format->flags);
+ GST_LOG_OBJECT (v4l2object->element, "description: '%s'",
+ format->description);
+ GST_LOG_OBJECT (v4l2object->element, "pixelformat: %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (format->pixelformat));
+
+ /* sort formats according to our preference; we do this, because caps
+ * are probed in the order the formats are in the list, and the order of
+ * formats in the final probed caps matters for things like fixation */
+ v4l2object->formats = g_slist_insert_sorted (v4l2object->formats, format,
+ (GCompareFunc) format_cmp_func);
+ }
+
+#ifndef GST_DISABLE_GST_DEBUG
+ {
+ GSList *l;
+
+ GST_INFO_OBJECT (v4l2object->element, "got %d format(s):", n);
+ for (l = v4l2object->formats; l != NULL; l = l->next) {
+ format = l->data;
+
+ GST_INFO_OBJECT (v4l2object->element,
+ " %" GST_FOURCC_FORMAT "%s", GST_FOURCC_ARGS (format->pixelformat),
+ ((format->flags & V4L2_FMT_FLAG_EMULATED)) ? " (emulated)" : "");
+ }
+ }
+#endif
+
+ return TRUE;
+
+ /* ERRORS */
+failed:
+ {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to enumerate possible video formats device '%s' can work with"), v4l2object->videodev), ("Failed to get number %d in pixelformat enumeration for %s. (%d - %s)", n, v4l2object->videodev, errno, g_strerror (errno)));
+ g_free (format);
+ return FALSE;
+ }
+}
+
+/*
+ * Get the list of supported capture formats, a list of
+ * <code>struct v4l2_fmtdesc</code>.
+ */
+GSList *
+gst_v4l2_object_get_format_list (GstV4l2Object * v4l2object)
+{
+ if (!v4l2object->formats)
+ gst_v4l2_object_fill_format_list (v4l2object);
+ return v4l2object->formats;
+}
+
+
+GstStructure *
+gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc)
+{
+ GstStructure *structure = NULL;
+
+ switch (fourcc) {
+ case V4L2_PIX_FMT_MJPEG: /* Motion-JPEG */
+#ifdef V4L2_PIX_FMT_PJPG
+ case V4L2_PIX_FMT_PJPG: /* Progressive-JPEG */
+#endif
+ case V4L2_PIX_FMT_JPEG: /* JFIF JPEG */
+ structure = gst_structure_new ("image/jpeg", NULL);
+ break;
+ case V4L2_PIX_FMT_RGB332:
+ case V4L2_PIX_FMT_RGB555:
+ case V4L2_PIX_FMT_RGB555X:
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_RGB565X:
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_BGR32:{
+ guint depth = 0, bpp = 0;
+
+ gint endianness = 0;
+
+ guint32 r_mask = 0, b_mask = 0, g_mask = 0;
+
+ switch (fourcc) {
+ case V4L2_PIX_FMT_RGB332:
+ bpp = depth = 8;
+ endianness = G_BYTE_ORDER; /* 'like, whatever' */
+ r_mask = 0xe0;
+ g_mask = 0x1c;
+ b_mask = 0x03;
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ case V4L2_PIX_FMT_RGB555X:
+ bpp = 16;
+ depth = 15;
+ endianness =
+ fourcc == V4L2_PIX_FMT_RGB555X ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
+ r_mask = 0x7c00;
+ g_mask = 0x03e0;
+ b_mask = 0x001f;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_RGB565X:
+ bpp = depth = 16;
+ endianness =
+ fourcc == V4L2_PIX_FMT_RGB565X ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
+ r_mask = 0xf800;
+ g_mask = 0x07e0;
+ b_mask = 0x001f;
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ bpp = depth = 24;
+ endianness = G_BIG_ENDIAN;
+ r_mask = 0xff0000;
+ g_mask = 0x00ff00;
+ b_mask = 0x0000ff;
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ bpp = depth = 24;
+ endianness = G_BIG_ENDIAN;
+ r_mask = 0x0000ff;
+ g_mask = 0x00ff00;
+ b_mask = 0xff0000;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ bpp = depth = 32;
+ endianness = G_BIG_ENDIAN;
+ r_mask = 0xff000000;
+ g_mask = 0x00ff0000;
+ b_mask = 0x0000ff00;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ bpp = depth = 32;
+ endianness = G_BIG_ENDIAN;
+ r_mask = 0x000000ff;
+ g_mask = 0x0000ff00;
+ b_mask = 0x00ff0000;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ structure = gst_structure_new ("video/x-raw-rgb",
+ "bpp", G_TYPE_INT, bpp,
+ "depth", G_TYPE_INT, depth,
+ "red_mask", G_TYPE_INT, r_mask,
+ "green_mask", G_TYPE_INT, g_mask,
+ "blue_mask", G_TYPE_INT, b_mask,
+ "endianness", G_TYPE_INT, endianness, NULL);
+ break;
+ }
+ case V4L2_PIX_FMT_GREY: /* 8 Greyscale */
+ structure = gst_structure_new ("video/x-raw-gray",
+ "bpp", G_TYPE_INT, 8, NULL);
+ break;
+ case V4L2_PIX_FMT_YYUV: /* 16 YUV 4:2:2 */
+ case V4L2_PIX_FMT_HI240: /* 8 8-bit color */
+ /* FIXME: get correct fourccs here */
+ break;
+ case V4L2_PIX_FMT_NV12: /* 12 Y/CbCr 4:2:0 */
+ case V4L2_PIX_FMT_NV21: /* 12 Y/CrCb 4:2:0 */
+ case V4L2_PIX_FMT_YVU410:
+ case V4L2_PIX_FMT_YUV410:
+ case V4L2_PIX_FMT_YUV420: /* I420/IYUV */
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVU420:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_Y41P:
+ case V4L2_PIX_FMT_YUV422P:
+#ifdef V4L2_PIX_FMT_YVYU
+ case V4L2_PIX_FMT_YVYU:
+#endif
+ case V4L2_PIX_FMT_YUV411P:{
+ guint32 fcc = 0;
+
+ switch (fourcc) {
+ case V4L2_PIX_FMT_NV12:
+ fcc = GST_MAKE_FOURCC ('N', 'V', '1', '2');
+ break;
+ case V4L2_PIX_FMT_NV21:
+ fcc = GST_MAKE_FOURCC ('N', 'V', '2', '1');
+ break;
+ case V4L2_PIX_FMT_YVU410:
+ fcc = GST_MAKE_FOURCC ('Y', 'V', 'U', '9');
+ break;
+ case V4L2_PIX_FMT_YUV410:
+ fcc = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ fcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ fcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ fcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ fcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
+ break;
+ case V4L2_PIX_FMT_Y41P:
+ fcc = GST_MAKE_FOURCC ('Y', '4', '1', 'P');
+ break;
+ case V4L2_PIX_FMT_YUV411P:
+ fcc = GST_MAKE_FOURCC ('Y', '4', '1', 'B');
+ break;
+ case V4L2_PIX_FMT_YUV422P:
+ fcc = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
+ break;
+#ifdef V4L2_PIX_FMT_YVYU
+ case V4L2_PIX_FMT_YVYU:
+ fcc = GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U');
+ break;
+#endif
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ structure = gst_structure_new ("video/x-raw-yuv",
+ "format", GST_TYPE_FOURCC, fcc, NULL);
+ break;
+ }
+ case V4L2_PIX_FMT_DV:
+ structure =
+ gst_structure_new ("video/x-dv", "systemstream", G_TYPE_BOOLEAN, TRUE,
+ NULL);
+ break;
+ case V4L2_PIX_FMT_MPEG: /* MPEG */
+ structure = gst_structure_new ("video/mpegts", NULL);
+ break;
+ case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */
+ break;
+#ifdef V4L2_PIX_FMT_SBGGR8
+ case V4L2_PIX_FMT_SBGGR8:
+ structure = gst_structure_new ("video/x-raw-bayer", NULL);
+ break;
+#endif
+#ifdef V4L2_PIX_FMT_SN9C10X
+ case V4L2_PIX_FMT_SN9C10X:
+ structure = gst_structure_new ("video/x-sonix", NULL);
+ break;
+#endif
+#ifdef V4L2_PIX_FMT_PWC1
+ case V4L2_PIX_FMT_PWC1:
+ structure = gst_structure_new ("video/x-pwc1", NULL);
+ break;
+#endif
+#ifdef V4L2_PIX_FMT_PWC2
+ case V4L2_PIX_FMT_PWC2:
+ structure = gst_structure_new ("video/x-pwc2", NULL);
+ break;
+#endif
+ default:
+ GST_DEBUG ("Unknown fourcc 0x%08x %" GST_FOURCC_FORMAT,
+ fourcc, GST_FOURCC_ARGS (fourcc));
+ break;
+ }
+
+ return structure;
+}
+
+
+
+GstCaps *
+gst_v4l2_object_get_all_caps (void)
+{
+ static GstCaps *caps = NULL;
+
+ if (caps == NULL) {
+ GstStructure *structure;
+
+ guint i;
+
+ caps = gst_caps_new_empty ();
+ for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) {
+ structure =
+ gst_v4l2_object_v4l2fourcc_to_structure (gst_v4l2_formats[i].format);
+ if (structure) {
+ if (gst_v4l2_formats[i].dimensions) {
+ gst_structure_set (structure,
+ "width", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE,
+ "height", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE,
+ "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 100, 1, NULL);
+ }
+ gst_caps_append_structure (caps, structure);
+ }
+ }
+ }
+
+ return gst_caps_ref (caps);
+}
+
+
+/* collect data for the given caps
+ * @caps: given input caps
+ * @format: location for the v4l format
+ * @w/@h: location for width and height
+ * @fps_n/@fps_d: location for framerate
+ * @size: location for expected size of the frame or 0 if unknown
+ */
+gboolean
+gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
+ struct v4l2_fmtdesc ** format, gint * w, gint * h,
+ gboolean * interlaced, guint * fps_n, guint * fps_d, guint * size)
+{
+ GstStructure *structure;
+ const GValue *framerate;
+ guint32 fourcc;
+ const gchar *mimetype;
+ guint outsize;
+
+ /* default unknown values */
+ fourcc = 0;
+ outsize = 0;
+
+ structure = gst_caps_get_structure (caps, 0);
+
+ mimetype = gst_structure_get_name (structure);
+
+ if (strcmp (mimetype, "video/mpegts") == 0) {
+ fourcc = V4L2_PIX_FMT_MPEG;
+ *fps_n = 0;
+ *fps_d = 1;
+ goto done;
+ }
+
+ if (!gst_structure_get_int (structure, "width", w))
+ return FALSE;
+
+ if (!gst_structure_get_int (structure, "height", h))
+ return FALSE;
+
+ if (!gst_structure_get_boolean (structure, "interlaced", interlaced))
+ *interlaced = FALSE;
+
+ framerate = gst_structure_get_value (structure, "framerate");
+ if (!framerate)
+ return FALSE;
+
+ *fps_n = gst_value_get_fraction_numerator (framerate);
+ *fps_d = gst_value_get_fraction_denominator (framerate);
+
+ if (!strcmp (mimetype, "video/x-raw-yuv")) {
+ gst_structure_get_fourcc (structure, "format", &fourcc);
+
+ switch (fourcc) {
+ case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+ case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
+ fourcc = V4L2_PIX_FMT_YUV420;
+ outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
+ outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
+ break;
+ case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
+ fourcc = V4L2_PIX_FMT_YUYV;
+ outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
+ break;
+ case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
+ fourcc = V4L2_PIX_FMT_Y41P;
+ outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
+ break;
+ case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
+ fourcc = V4L2_PIX_FMT_UYVY;
+ outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
+ break;
+ case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
+ fourcc = V4L2_PIX_FMT_YVU420;
+ outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
+ outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
+ break;
+ case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
+ fourcc = V4L2_PIX_FMT_YUV411P;
+ outsize = GST_ROUND_UP_4 (*w) * *h;
+ outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
+ break;
+ case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
+ fourcc = V4L2_PIX_FMT_YUV422P;
+ outsize = GST_ROUND_UP_4 (*w) * *h;
+ outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
+ break;
+ case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
+ fourcc = V4L2_PIX_FMT_NV12;
+ outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
+ outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
+ break;
+ case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
+ fourcc = V4L2_PIX_FMT_NV21;
+ outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
+ outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
+ break;
+#ifdef V4L2_PIX_FMT_YVYU
+ case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
+ fourcc = V4L2_PIX_FMT_YVYU;
+ outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
+ break;
+#endif
+ }
+ } else if (!strcmp (mimetype, "video/x-raw-rgb")) {
+ gint depth, endianness, r_mask;
+
+ gst_structure_get_int (structure, "depth", &depth);
+ gst_structure_get_int (structure, "endianness", &endianness);
+ gst_structure_get_int (structure, "red_mask", &r_mask);
+
+ switch (depth) {
+ case 8:
+ fourcc = V4L2_PIX_FMT_RGB332;
+ break;
+ case 15:
+ fourcc = (endianness == G_LITTLE_ENDIAN) ?
+ V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X;
+ break;
+ case 16:
+ fourcc = (endianness == G_LITTLE_ENDIAN) ?
+ V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X;
+ break;
+ case 24:
+ fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24;
+ break;
+ case 32:
+ fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32;
+ break;
+ }
+ } else if (strcmp (mimetype, "video/x-dv") == 0) {
+ fourcc = V4L2_PIX_FMT_DV;
+ } else if (strcmp (mimetype, "image/jpeg") == 0) {
+ fourcc = V4L2_PIX_FMT_JPEG;
+#ifdef V4L2_PIX_FMT_SBGGR8
+ } else if (strcmp (mimetype, "video/x-raw-bayer") == 0) {
+ fourcc = V4L2_PIX_FMT_SBGGR8;
+#endif
+#ifdef V4L2_PIX_FMT_SN9C10X
+ } else if (strcmp (mimetype, "video/x-sonix") == 0) {
+ fourcc = V4L2_PIX_FMT_SN9C10X;
+#endif
+#ifdef V4L2_PIX_FMT_PWC1
+ } else if (strcmp (mimetype, "video/x-pwc1") == 0) {
+ fourcc = V4L2_PIX_FMT_PWC1;
+#endif
+#ifdef V4L2_PIX_FMT_PWC2
+ } else if (strcmp (mimetype, "video/x-pwc2") == 0) {
+ fourcc = V4L2_PIX_FMT_PWC2;
+#endif
+ } else if (strcmp (mimetype, "video/x-raw-gray") == 0) {
+ fourcc = V4L2_PIX_FMT_GREY;
+ }
+
+ if (fourcc == 0)
+ return FALSE;
+
+done:
+ *format = gst_v4l2_object_get_format_from_fourcc (v4l2object, fourcc);
+ *size = outsize;
+
+ return TRUE;
+}
+
+
+static gboolean
+gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
+ guint32 pixelformat, gint * width, gint * height, gboolean * interlaced);
+
+
+/* The frame interval enumeration code first appeared in Linux 2.6.19. */
+#ifdef VIDIOC_ENUM_FRAMEINTERVALS
+static GstStructure *
+gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object,
+ guint32 pixelformat,
+ guint32 width, guint32 height, const GstStructure * template)
+{
+ gint fd = v4l2object->video_fd;
+ struct v4l2_frmivalenum ival;
+ guint32 num, denom;
+ GstStructure *s;
+ GValue rates = { 0, };
+ gboolean interlaced;
+ gint int_width = width;
+ gint int_height = height;
+
+ /* interlaced detection using VIDIOC_TRY/S_FMT */
+ if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat,
+ &int_width, &int_height, &interlaced))
+ return NULL;
+
+ memset (&ival, 0, sizeof (struct v4l2_frmivalenum));
+ ival.index = 0;
+ ival.pixel_format = pixelformat;
+ ival.width = width;
+ ival.height = height;
+
+ GST_LOG_OBJECT (v4l2object->element,
+ "get frame interval for %ux%u, %" GST_FOURCC_FORMAT, width, height,
+ GST_FOURCC_ARGS (pixelformat));
+
+ /* keep in mind that v4l2 gives us frame intervals (durations); we invert the
+ * fraction to get framerate */
+ if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0)
+ goto enum_frameintervals_failed;
+
+ if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
+ GValue rate = { 0, };
+
+ g_value_init (&rates, GST_TYPE_LIST);
+ g_value_init (&rate, GST_TYPE_FRACTION);
+
+ do {
+ num = ival.discrete.numerator;
+ denom = ival.discrete.denominator;
+
+ if (num > G_MAXINT || denom > G_MAXINT) {
+ /* let us hope we don't get here... */
+ num >>= 1;
+ denom >>= 1;
+ }
+
+ GST_LOG_OBJECT (v4l2object->element, "adding discrete framerate: %d/%d",
+ denom, num);
+
+ /* swap to get the framerate */
+ gst_value_set_fraction (&rate, denom, num);
+ gst_value_list_append_value (&rates, &rate);
+
+ ival.index++;
+ } while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
+ } else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
+ GValue min = { 0, };
+ GValue step = { 0, };
+ GValue max = { 0, };
+ gboolean added = FALSE;
+ guint32 minnum, mindenom;
+ guint32 maxnum, maxdenom;
+
+ g_value_init (&rates, GST_TYPE_LIST);
+
+ g_value_init (&min, GST_TYPE_FRACTION);
+ g_value_init (&step, GST_TYPE_FRACTION);
+ g_value_init (&max, GST_TYPE_FRACTION);
+
+ /* get the min */
+ minnum = ival.stepwise.min.numerator;
+ mindenom = ival.stepwise.min.denominator;
+ if (minnum > G_MAXINT || mindenom > G_MAXINT) {
+ minnum >>= 1;
+ mindenom >>= 1;
+ }
+ GST_LOG_OBJECT (v4l2object->element, "stepwise min frame interval: %d/%d",
+ minnum, mindenom);
+ gst_value_set_fraction (&min, minnum, mindenom);
+
+ /* get the max */
+ maxnum = ival.stepwise.max.numerator;
+ maxdenom = ival.stepwise.max.denominator;
+ if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
+ maxnum >>= 1;
+ maxdenom >>= 1;
+ }
+
+ GST_LOG_OBJECT (v4l2object->element, "stepwise max frame interval: %d/%d",
+ maxnum, maxdenom);
+ gst_value_set_fraction (&max, maxnum, maxdenom);
+
+ /* get the step */
+ num = ival.stepwise.step.numerator;
+ denom = ival.stepwise.step.denominator;
+ if (num > G_MAXINT || denom > G_MAXINT) {
+ num >>= 1;
+ denom >>= 1;
+ }
+
+ if (num == 0 || denom == 0) {
+ /* in this case we have a wrong fraction or no step, set the step to max
+ * so that we only add the min value in the loop below */
+ num = maxnum;
+ denom = maxdenom;
+ }
+
+ /* since we only have gst_value_fraction_subtract and not add, negate the
+ * numerator */
+ GST_LOG_OBJECT (v4l2object->element, "stepwise step frame interval: %d/%d",
+ num, denom);
+ gst_value_set_fraction (&step, -num, denom);
+
+ while (gst_value_compare (&min, &max) != GST_VALUE_GREATER_THAN) {
+ GValue rate = { 0, };
+
+ num = gst_value_get_fraction_numerator (&min);
+ denom = gst_value_get_fraction_denominator (&min);
+ GST_LOG_OBJECT (v4l2object->element, "adding stepwise framerate: %d/%d",
+ denom, num);
+
+ /* invert to get the framerate */
+ g_value_init (&rate, GST_TYPE_FRACTION);
+ gst_value_set_fraction (&rate, denom, num);
+ gst_value_list_append_value (&rates, &rate);
+ added = TRUE;
+
+ /* we're actually adding because step was negated above. This is because
+ * there is no _add function... */
+ if (!gst_value_fraction_subtract (&min, &min, &step)) {
+ GST_WARNING_OBJECT (v4l2object->element, "could not step fraction!");
+ break;
+ }
+ }
+ if (!added) {
+ /* no range was added, leave the default range from the template */
+ GST_WARNING_OBJECT (v4l2object->element,
+ "no range added, leaving default");
+ g_value_unset (&rates);
+ }
+ } else if (ival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
+ guint32 maxnum, maxdenom;
+
+ g_value_init (&rates, GST_TYPE_FRACTION_RANGE);
+
+ num = ival.stepwise.min.numerator;
+ denom = ival.stepwise.min.denominator;
+ if (num > G_MAXINT || denom > G_MAXINT) {
+ num >>= 1;
+ denom >>= 1;
+ }
+
+ maxnum = ival.stepwise.max.numerator;
+ maxdenom = ival.stepwise.max.denominator;
+ if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
+ maxnum >>= 1;
+ maxdenom >>= 1;
+ }
+
+ GST_LOG_OBJECT (v4l2object->element,
+ "continuous frame interval %d/%d to %d/%d", maxdenom, maxnum, denom,
+ num);
+
+ gst_value_set_fraction_range_full (&rates, maxdenom, maxnum, denom, num);
+ } else {
+ goto unknown_type;
+ }
+
+return_data:
+ s = gst_structure_copy (template);
+ gst_structure_set (s, "width", G_TYPE_INT, (gint) width,
+ "height", G_TYPE_INT, (gint) height,
+ "interlaced", G_TYPE_BOOLEAN, interlaced,
+ "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
+
+ if (G_IS_VALUE (&rates)) {
+ /* only change the framerate on the template when we have a valid probed new
+ * value */
+ gst_structure_set_value (s, "framerate", &rates);
+ g_value_unset (&rates);
+ } else {
+ gst_structure_set (s, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 100, 1,
+ NULL);
+ }
+ return s;
+
+ /* ERRORS */
+enum_frameintervals_failed:
+ {
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "Unable to enumerate intervals for %" GST_FOURCC_FORMAT "@%ux%u",
+ GST_FOURCC_ARGS (pixelformat), width, height);
+ goto return_data;
+ }
+unknown_type:
+ {
+ /* I don't see how this is actually an error, we ignore the format then */
+ GST_WARNING_OBJECT (v4l2object->element,
+ "Unknown frame interval type at %" GST_FOURCC_FORMAT "@%ux%u: %u",
+ GST_FOURCC_ARGS (pixelformat), width, height, ival.type);
+ return NULL;
+ }
+}
+#endif /* defined VIDIOC_ENUM_FRAMEINTERVALS */
+
+#ifdef VIDIOC_ENUM_FRAMESIZES
+static gint
+sort_by_frame_size (GstStructure * s1, GstStructure * s2)
+{
+ int w1, h1, w2, h2;
+
+ gst_structure_get_int (s1, "width", &w1);
+ gst_structure_get_int (s1, "height", &h1);
+ gst_structure_get_int (s2, "width", &w2);
+ gst_structure_get_int (s2, "height", &h2);
+
+ /* I think it's safe to assume that this won't overflow for a while */
+ return ((w2 * h2) - (w1 * h1));
+}
+#endif
+
+GstCaps *
+gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object,
+ guint32 pixelformat, const GstStructure * template)
+{
+ GstCaps *ret = gst_caps_new_empty ();
+ GstStructure *tmp;
+
+#ifdef VIDIOC_ENUM_FRAMESIZES
+ gint fd = v4l2object->video_fd;
+ struct v4l2_frmsizeenum size;
+ GList *results = NULL;
+ guint32 w, h;
+
+ if (pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G'))
+ return gst_caps_new_simple ("video/mpegts", NULL);
+
+ memset (&size, 0, sizeof (struct v4l2_frmsizeenum));
+ size.index = 0;
+ size.pixel_format = pixelformat;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "Enumerating frame sizes");
+
+ if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0)
+ goto enum_framesizes_failed;
+
+ if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+ do {
+ GST_LOG_OBJECT (v4l2object->element, "got discrete frame size %dx%d",
+ size.discrete.width, size.discrete.height);
+
+ w = MIN (size.discrete.width, G_MAXINT);
+ h = MIN (size.discrete.height, G_MAXINT);
+
+ if (w && h) {
+ tmp =
+ gst_v4l2_object_probe_caps_for_format_and_size (v4l2object,
+ pixelformat, w, h, template);
+
+ if (tmp)
+ results = g_list_prepend (results, tmp);
+ }
+
+ size.index++;
+ } while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "done iterating discrete frame sizes");
+ } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
+ GST_DEBUG_OBJECT (v4l2object->element, "we have stepwise frame sizes:");
+ GST_DEBUG_OBJECT (v4l2object->element, "min width: %d",
+ size.stepwise.min_width);
+ GST_DEBUG_OBJECT (v4l2object->element, "min height: %d",
+ size.stepwise.min_height);
+ GST_DEBUG_OBJECT (v4l2object->element, "max width: %d",
+ size.stepwise.max_width);
+ GST_DEBUG_OBJECT (v4l2object->element, "min height: %d",
+ size.stepwise.max_height);
+ GST_DEBUG_OBJECT (v4l2object->element, "step width: %d",
+ size.stepwise.step_width);
+ GST_DEBUG_OBJECT (v4l2object->element, "step height: %d",
+ size.stepwise.step_height);
+
+ for (w = size.stepwise.min_width, h = size.stepwise.min_height;
+ w <= size.stepwise.max_width && h <= size.stepwise.max_height;
+ w += size.stepwise.step_width, h += size.stepwise.step_height) {
+ if (w == 0 || h == 0)
+ continue;
+
+ tmp =
+ gst_v4l2_object_probe_caps_for_format_and_size (v4l2object,
+ pixelformat, w, h, template);
+
+ if (tmp)
+ results = g_list_prepend (results, tmp);
+ }
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "done iterating stepwise frame sizes");
+ } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
+ guint32 maxw, maxh;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "we have continuous frame sizes:");
+ GST_DEBUG_OBJECT (v4l2object->element, "min width: %d",
+ size.stepwise.min_width);
+ GST_DEBUG_OBJECT (v4l2object->element, "min height: %d",
+ size.stepwise.min_height);
+ GST_DEBUG_OBJECT (v4l2object->element, "max width: %d",
+ size.stepwise.max_width);
+ GST_DEBUG_OBJECT (v4l2object->element, "min height: %d",
+ size.stepwise.max_height);
+
+ w = MAX (size.stepwise.min_width, 1);
+ h = MAX (size.stepwise.min_height, 1);
+ maxw = MIN (size.stepwise.max_width, G_MAXINT);
+ maxh = MIN (size.stepwise.max_height, G_MAXINT);
+
+ tmp =
+ gst_v4l2_object_probe_caps_for_format_and_size (v4l2object, pixelformat,
+ w, h, template);
+ if (tmp) {
+ gst_structure_set (tmp, "width", GST_TYPE_INT_RANGE, (gint) w,
+ (gint) maxw, "height", GST_TYPE_INT_RANGE, (gint) h, (gint) maxh,
+ NULL);
+
+ /* no point using the results list here, since there's only one struct */
+ gst_caps_append_structure (ret, tmp);
+ }
+ } else {
+ goto unknown_type;
+ }
+
+ /* we use an intermediary list to store and then sort the results of the
+ * probing because we can't make any assumptions about the order in which
+ * the driver will give us the sizes, but we want the final caps to contain
+ * the results starting with the highest resolution and having the lowest
+ * resolution last, since order in caps matters for things like fixation. */
+ results = g_list_sort (results, (GCompareFunc) sort_by_frame_size);
+ while (results != NULL) {
+ gst_caps_append_structure (ret, GST_STRUCTURE (results->data));
+ results = g_list_delete_link (results, results);
+ }
+
+ if (gst_caps_is_empty (ret))
+ goto enum_framesizes_no_results;
+
+ return ret;
+
+ /* ERRORS */
+enum_framesizes_failed:
+ {
+ /* I don't see how this is actually an error */
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "Failed to enumerate frame sizes for pixelformat %" GST_FOURCC_FORMAT
+ " (%s)", GST_FOURCC_ARGS (pixelformat), g_strerror (errno));
+ goto default_frame_sizes;
+ }
+enum_framesizes_no_results:
+ {
+ /* it's possible that VIDIOC_ENUM_FRAMESIZES is defined but the driver in
+ * question doesn't actually support it yet */
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "No results for pixelformat %" GST_FOURCC_FORMAT
+ " enumerating frame sizes, trying fallback",
+ GST_FOURCC_ARGS (pixelformat));
+ goto default_frame_sizes;
+ }
+unknown_type:
+ {
+ GST_WARNING_OBJECT (v4l2object->element,
+ "Unknown frame sizeenum type for pixelformat %" GST_FOURCC_FORMAT
+ ": %u", GST_FOURCC_ARGS (pixelformat), size.type);
+ goto default_frame_sizes;
+ }
+default_frame_sizes:
+#endif /* defined VIDIOC_ENUM_FRAMESIZES */
+ {
+ gint min_w, max_w, min_h, max_h, fix_num = 0, fix_denom = 0;
+ gboolean interlaced;
+
+ /* This code is for Linux < 2.6.19 */
+ min_w = min_h = 1;
+ max_w = max_h = GST_V4L2_MAX_SIZE;
+ if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, &min_w,
+ &min_h, &interlaced)) {
+ GST_WARNING_OBJECT (v4l2object->element,
+ "Could not probe minimum capture size for pixelformat %"
+ GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
+ }
+ if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, &max_w,
+ &max_h, &interlaced)) {
+ GST_WARNING_OBJECT (v4l2object->element,
+ "Could not probe maximum capture size for pixelformat %"
+ GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
+ }
+
+ /* Since we can't get framerate directly, try to use the current norm */
+ if (v4l2object->tv_norm && v4l2object->norms) {
+ GList *norms;
+ GstTunerNorm *norm = NULL;
+ GstTunerNorm *current =
+ gst_v4l2_tuner_get_norm_by_std_id (v4l2object, v4l2object->tv_norm);
+
+ for (norms = v4l2object->norms; norms != NULL; norms = norms->next) {
+ norm = (GstTunerNorm *) norms->data;
+ if (!strcmp (norm->label, current->label))
+ break;
+ }
+ /* If it's possible, set framerate to that (discrete) value */
+ if (norm) {
+ fix_num = gst_value_get_fraction_numerator (&norm->framerate);
+ fix_denom = gst_value_get_fraction_denominator (&norm->framerate);
+ }
+ }
+
+ tmp = gst_structure_copy (template);
+ if (fix_num) {
+ gst_structure_set (tmp, "framerate", GST_TYPE_FRACTION, fix_num,
+ fix_denom, NULL);
+ } else {
+ /* if norm can't be used, copy the template framerate */
+ gst_structure_set (tmp, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1,
+ 100, 1, NULL);
+ }
+
+ if (min_w == max_w)
+ gst_structure_set (tmp, "width", G_TYPE_INT, max_w, NULL);
+ else
+ gst_structure_set (tmp, "width", GST_TYPE_INT_RANGE, min_w, max_w, NULL);
+
+ if (min_h == max_h)
+ gst_structure_set (tmp, "height", G_TYPE_INT, max_h, NULL);
+ else
+ gst_structure_set (tmp, "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL);
+
+ gst_structure_set (tmp, "interlaced", G_TYPE_BOOLEAN, interlaced, NULL);
+ gst_structure_set (tmp, "pixel-aspect-ratio",
+ GST_TYPE_FRACTION, 1, 1, NULL);
+
+ gst_caps_append_structure (ret, tmp);
+
+ return ret;
+ }
+}
+
+static gboolean
+gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
+ guint32 pixelformat, gint * width, gint * height, gboolean * interlaced)
+{
+ struct v4l2_format fmt, prevfmt;
+ int fd;
+ int r;
+ int prevfmt_valid;
+
+ g_return_val_if_fail (width != NULL, FALSE);
+ g_return_val_if_fail (height != NULL, FALSE);
+
+ GST_LOG_OBJECT (v4l2object->element,
+ "getting nearest size to %dx%d with format %" GST_FOURCC_FORMAT,
+ *width, *height, GST_FOURCC_ARGS (pixelformat));
+
+ fd = v4l2object->video_fd;
+
+ /* Some drivers are buggy and will modify the currently set format
+ when processing VIDIOC_TRY_FMT, so we remember what is set at the
+ minute, and will reset it when done. */
+ prevfmt_valid = (v4l2_ioctl (fd, VIDIOC_G_FMT, &prevfmt) >= 0);
+
+ /* get size delimiters */
+ memset (&fmt, 0, sizeof (fmt));
+ fmt.type = v4l2object->type;
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+ fmt.fmt.pix.pixelformat = pixelformat;
+ fmt.fmt.pix.field = V4L2_FIELD_NONE;
+
+ r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
+ if (r < 0 && errno == EINVAL) {
+ /* try again with interlaced video */
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+ fmt.fmt.pix.pixelformat = pixelformat;
+ fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+ r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
+ }
+
+ if (r < 0) {
+ /* The driver might not implement TRY_FMT, in which case we will try
+ S_FMT to probe */
+ if (errno != ENOTTY)
+ goto error;
+
+ /* Only try S_FMT if we're not actively capturing yet, which we shouldn't
+ be, because we're still probing */
+ if (GST_V4L2_IS_ACTIVE (v4l2object))
+ goto error;
+
+ GST_LOG_OBJECT (v4l2object->element,
+ "Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
+
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+
+ r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
+ if (r < 0 && errno == EINVAL) {
+ /* try again with progressive video */
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+ fmt.fmt.pix.pixelformat = pixelformat;
+ fmt.fmt.pix.field = V4L2_FIELD_NONE;
+ r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
+ }
+
+ if (r < 0)
+ goto error;
+ }
+
+ GST_LOG_OBJECT (v4l2object->element,
+ "got nearest size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
+
+ *width = fmt.fmt.pix.width;
+ *height = fmt.fmt.pix.height;
+
+ switch (fmt.fmt.pix.field) {
+ case V4L2_FIELD_ANY:
+ case V4L2_FIELD_NONE:
+ *interlaced = FALSE;
+ break;
+ case V4L2_FIELD_INTERLACED:
+ case V4L2_FIELD_INTERLACED_TB:
+ case V4L2_FIELD_INTERLACED_BT:
+ *interlaced = TRUE;
+ break;
+ default:
+ GST_WARNING_OBJECT (v4l2object->element,
+ "Unsupported field type for %" GST_FOURCC_FORMAT "@%ux%u",
+ GST_FOURCC_ARGS (pixelformat), *width, *height);
+ goto error;
+ }
+
+ if (prevfmt_valid)
+ v4l2_ioctl (fd, VIDIOC_S_FMT, &prevfmt);
+ return TRUE;
+
+error:
+ if (prevfmt_valid)
+ v4l2_ioctl (fd, VIDIOC_S_FMT, &prevfmt);
+ return FALSE;
+}
+
+
+gboolean
+gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat,
+ guint32 width, guint32 height, gboolean interlaced)
+{
+ gint fd = v4l2object->video_fd;
+ struct v4l2_format format;
+ enum v4l2_field field;
+
+ if (interlaced) {
+ GST_DEBUG_OBJECT (v4l2object->element, "interlaced video");
+ /* ideally we would differentiate between types of interlaced video
+ * but there is not sufficient information in the caps..
+ */
+ field = V4L2_FIELD_INTERLACED;
+ } else {
+ GST_DEBUG_OBJECT (v4l2object->element, "progressive video");
+ field = V4L2_FIELD_NONE;
+ }
+
+ GST_DEBUG_OBJECT (v4l2object->element, "Setting format to %dx%d, format "
+ "%" GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat));
+
+ GST_V4L2_CHECK_OPEN (v4l2object);
+ GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);
+
+ /* Only unconditionally accept mpegts for sources */
+ if ((v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+ (pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G')))
+ return TRUE;
+
+ memset (&format, 0x00, sizeof (struct v4l2_format));
+ format.type = v4l2object->type;
+
+ if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0)
+ goto get_fmt_failed;
+
+ if (format.type == v4l2object->type &&
+ format.fmt.pix.width == width &&
+ format.fmt.pix.height == height &&
+ format.fmt.pix.pixelformat == pixelformat &&
+ format.fmt.pix.field == field) {
+ /* Nothing to do. We want to succeed immediately
+ * here because setting the same format back
+ * can still fail due to EBUSY. By short-circuiting
+ * here, we allow pausing and re-playing pipelines
+ * with changed caps, as long as the changed caps
+ * do not change the webcam's format. Otherwise,
+ * any caps change would require us to go to NULL
+ * state to close the device and set format.
+ */
+ return TRUE;
+ }
+
+ format.type = v4l2object->type;
+ format.fmt.pix.width = width;
+ format.fmt.pix.height = height;
+ format.fmt.pix.pixelformat = pixelformat;
+ format.fmt.pix.field = field;
+
+ if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
+ goto set_fmt_failed;
+ }
+
+ if (format.fmt.pix.width != width || format.fmt.pix.height != height)
+ goto invalid_dimensions;
+
+ if (format.fmt.pix.pixelformat != pixelformat)
+ goto invalid_pixelformat;
+
+ return TRUE;
+
+ /* ERRORS */
+get_fmt_failed:
+ {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Device '%s' does not support video capture"),
+ v4l2object->videodev),
+ ("Call to G_FMT failed: (%s)", g_strerror (errno)));
+ return FALSE;
+ }
+set_fmt_failed:
+ {
+ if (errno == EBUSY) {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, BUSY,
+ (_("Device '%s' is busy"), v4l2object->videodev),
+ ("Call to S_FMT failed for %" GST_FOURCC_FORMAT " @ %dx%d: %s",
+ GST_FOURCC_ARGS (pixelformat), width, height,
+ g_strerror (errno)));
+ } else {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Device '%s' cannot capture at %dx%d"),
+ v4l2object->videodev, width, height),
+ ("Call to S_FMT failed for %" GST_FOURCC_FORMAT " @ %dx%d: %s",
+ GST_FOURCC_ARGS (pixelformat), width, height,
+ g_strerror (errno)));
+ }
+ return FALSE;
+ }
+invalid_dimensions:
+ {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Device '%s' cannot capture at %dx%d"),
+ v4l2object->videodev, width, height),
+ ("Tried to capture at %dx%d, but device returned size %dx%d",
+ width, height, format.fmt.pix.width, format.fmt.pix.height));
+ return FALSE;
+ }
+invalid_pixelformat:
+ {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Device '%s' cannot capture in the specified format"),
+ v4l2object->videodev),
+ ("Tried to capture in %" GST_FOURCC_FORMAT
+ ", but device returned format" " %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (pixelformat),
+ GST_FOURCC_ARGS (format.fmt.pix.pixelformat)));
+ return FALSE;
+ }
+}
+
+gboolean
+gst_v4l2_object_start_streaming (GstV4l2Object * v4l2object)
+{
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_STREAMON,
+ &(v4l2object->type)) < 0) {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, OPEN_READ,
+ (_("Error starting streaming on device '%s'."), v4l2object->videodev),
+ GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+gboolean
+gst_v4l2_object_stop_streaming (GstV4l2Object * v4l2object)
+{
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_STREAMOFF,
+ &(v4l2object->type)) < 0) {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, OPEN_READ,
+ (_("Error stopping streaming on device '%s'."), v4l2object->videodev),
+ GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
new file mode 100644
index 0000000..a7b590d
--- /dev/null
+++ b/sys/v4l2/gstv4l2object.h
@@ -0,0 +1,242 @@
+/* GStreamer
+ *
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2object.h: base class for V4L2 elements
+ *
+ * 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.
+ */
+
+#ifndef __GST_V4L2_OBJECT_H__
+#define __GST_V4L2_OBJECT_H__
+
+/* Because of some really cool feature in video4linux1, also known as
+ * 'not including sys/types.h and sys/time.h', we had to include it
+ * ourselves. In all their intelligence, these people decided to fix
+ * this in the next version (video4linux2) in such a cool way that it
+ * breaks all compilations of old stuff...
+ * The real problem is actually that linux/time.h doesn't use proper
+ * macro checks before defining types like struct timeval. The proper
+ * fix here is to either fuck the kernel header (which is what we do
+ * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it
+ * upstream, which I'll consider doing later on. If you get compiler
+ * errors here, check your linux/time.h && sys/time.h header setup.
+ */
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#ifndef __sun
+#include <linux/types.h>
+#define _LINUX_TIME_H
+#define __user
+#include <linux/videodev2.h>
+#else
+#include <sys/videodev2.h>
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstpushsrc.h>
+#include <gst/controller/gstcontroller.h>
+
+#include <gst/interfaces/propertyprobe.h>
+
+
+/* size of v4l2 buffer pool in streaming case */
+#define GST_V4L2_MAX_BUFFERS 16
+#define GST_V4L2_MIN_BUFFERS 1
+
+/* max frame width/height */
+#define GST_V4L2_MAX_SIZE (1<<15) /* 2^15 == 32768 */
+
+
+
+G_BEGIN_DECLS
+
+#define GST_V4L2_OBJECT(obj) (GstV4l2Object *)(obj)
+
+typedef struct _GstV4l2Object GstV4l2Object;
+typedef struct _GstV4l2ObjectClassHelper GstV4l2ObjectClassHelper;
+typedef struct _GstV4l2Xv GstV4l2Xv;
+
+typedef gboolean (*GstV4l2GetInOutFunction) (GstV4l2Object * v4l2object, gint * input);
+typedef gboolean (*GstV4l2SetInOutFunction) (GstV4l2Object * v4l2object, gint input);
+typedef gboolean (*GstV4l2UpdateFpsFunction) (GstV4l2Object * v4l2object);
+
+struct _GstV4l2Object {
+ GstElement * element;
+
+ /* the video device */
+ char *videodev;
+
+ /* the video-device's file descriptor */
+ gint video_fd;
+ GstPoll * poll;
+ gboolean can_poll_device;
+
+ /* the video buffer (mmap()'ed) */
+ guint8 **buffer;
+
+ enum v4l2_buf_type type; /* V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_OUTPUT */
+
+ /* the video device's capabilities */
+ struct v4l2_capability vcap;
+
+ /* the video device's window properties */
+ struct v4l2_window vwin;
+
+ /* some more info about the current input's capabilities */
+ struct v4l2_input vinput;
+
+ /* lists... */
+ GSList *formats; /* list of available capture formats */
+
+ GList *colors;
+ GList *norms;
+ GList *channels;
+
+ /* properties */
+ v4l2_std_id tv_norm;
+ gchar *channel;
+ gulong frequency;
+
+ /* X-overlay */
+ GstV4l2Xv *xv;
+ gulong xwindow_id;
+
+ /* funcs */
+ GstV4l2GetInOutFunction get_in_out_func;
+ GstV4l2SetInOutFunction set_in_out_func;
+ GstV4l2UpdateFpsFunction update_fps_func;
+};
+
+struct _GstV4l2ObjectClassHelper {
+ /* probed devices */
+ GList *devices;
+};
+
+GType gst_v4l2_object_get_type (void);
+
+#define V4L2_STD_OBJECT_PROPS \
+ PROP_DEVICE, \
+ PROP_DEVICE_NAME, \
+ PROP_DEVICE_FD, \
+ PROP_FLAGS, \
+ PROP_BRIGHTNESS, \
+ PROP_CONTRAST, \
+ PROP_SATURATION, \
+ PROP_HUE, \
+ PROP_TV_NORM
+
+/* create/destroy */
+GstV4l2Object * gst_v4l2_object_new (GstElement * element,
+ enum v4l2_buf_type type,
+ const char *default_device,
+ GstV4l2GetInOutFunction get_in_out_func,
+ GstV4l2SetInOutFunction set_in_out_func,
+ GstV4l2UpdateFpsFunction update_fps_func);
+void gst_v4l2_object_destroy (GstV4l2Object * v4l2object);
+
+/* properties */
+
+void gst_v4l2_object_install_properties_helper (GObjectClass *gobject_class, const char *default_device);
+
+gboolean gst_v4l2_object_set_property_helper (GstV4l2Object *v4l2object,
+ guint prop_id, const GValue * value,
+ GParamSpec * pspec);
+gboolean gst_v4l2_object_get_property_helper (GstV4l2Object *v4l2object,
+ guint prop_id, GValue * value,
+ GParamSpec * pspec);
+/* starting/stopping */
+gboolean gst_v4l2_object_start (GstV4l2Object *v4l2object);
+gboolean gst_v4l2_object_stop (GstV4l2Object *v4l2object);
+
+/* probing */
+const GList* gst_v4l2_probe_get_properties (GstPropertyProbe * probe);
+
+void gst_v4l2_probe_probe_property (GstPropertyProbe * probe, guint prop_id,
+ const GParamSpec * pspec,
+ GList ** klass_devices);
+gboolean gst_v4l2_probe_needs_probe (GstPropertyProbe * probe, guint prop_id,
+ const GParamSpec * pspec,
+ GList ** klass_devices);
+GValueArray* gst_v4l2_probe_get_values (GstPropertyProbe * probe, guint prop_id,
+ const GParamSpec * pspec,
+ GList ** klass_devices);
+
+GstCaps* gst_v4l2_object_probe_caps_for_format (GstV4l2Object *v4l2object, guint32 pixelformat,
+ const GstStructure * template);
+
+gboolean gst_v4l2_object_get_caps_info (GstV4l2Object *v4l2object, GstCaps *caps,
+ struct v4l2_fmtdesc **format, gint *w, gint *h,
+ gboolean * interlaced, guint *fps_n, guint *fps_d, guint *size);
+
+
+GSList* gst_v4l2_object_get_format_list (GstV4l2Object *v4l2object);
+
+GstCaps* gst_v4l2_object_get_all_caps (void);
+
+GstStructure* gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc);
+
+gboolean gst_v4l2_object_set_format (GstV4l2Object *v4l2object, guint32 pixelformat, guint32 width, guint32 height, gboolean interlaced);
+
+gboolean gst_v4l2_object_start_streaming (GstV4l2Object *v4l2object);
+gboolean gst_v4l2_object_stop_streaming (GstV4l2Object *v4l2object);
+
+
+#define GST_IMPLEMENT_V4L2_PROBE_METHODS(Type_Class, interface_as_function) \
+ \
+static void \
+interface_as_function ## _probe_probe_property (GstPropertyProbe * probe, \
+ guint prop_id, \
+ const GParamSpec * pspec) \
+{ \
+ Type_Class *this_class = (Type_Class*) G_OBJECT_GET_CLASS (probe); \
+ gst_v4l2_probe_probe_property (probe, prop_id, pspec, \
+ &this_class->v4l2_class_devices); \
+} \
+ \
+static gboolean \
+interface_as_function ## _probe_needs_probe (GstPropertyProbe * probe, \
+ guint prop_id, \
+ const GParamSpec * pspec) \
+{ \
+ Type_Class *this_class = (Type_Class*) G_OBJECT_GET_CLASS (probe); \
+ return gst_v4l2_probe_needs_probe (probe, prop_id, pspec, \
+ &this_class->v4l2_class_devices); \
+} \
+ \
+static GValueArray * \
+interface_as_function ## _probe_get_values (GstPropertyProbe * probe, \
+ guint prop_id, \
+ const GParamSpec * pspec) \
+{ \
+ Type_Class *this_class = (Type_Class*) G_OBJECT_GET_CLASS (probe); \
+ return gst_v4l2_probe_get_values (probe, prop_id, pspec, \
+ &this_class->v4l2_class_devices); \
+} \
+ \
+static void \
+interface_as_function ## _property_probe_interface_init (GstPropertyProbeInterface * iface) \
+{ \
+ iface->get_properties = gst_v4l2_probe_get_properties; \
+ iface->probe_property = interface_as_function ## _probe_probe_property; \
+ iface->needs_probe = interface_as_function ## _probe_needs_probe; \
+ iface->get_values = interface_as_function ## _probe_get_values; \
+}
+
+G_END_DECLS
+
+#endif /* __GST_V4L2_OBJECT_H__ */
diff --git a/sys/v4l2/gstv4l2radio.c b/sys/v4l2/gstv4l2radio.c
new file mode 100644
index 0000000..63a2fed
--- /dev/null
+++ b/sys/v4l2/gstv4l2radio.c
@@ -0,0 +1,635 @@
+/* GStreamer v4l2 radio tuner element
+ * Copyright (C) 2010, 2011 Alexey Chernov <4ernov@gmail.com>
+ *
+ * gstv4l2radio.c - V4L2 radio tuner element
+ *
+ * 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-v4l2radio
+ *
+ * v4l2radio can be used to control radio device
+ * and to tune it to different radiostations.
+ *
+ * <refsect2>
+ * <title>Example launch lines</title>
+ * |[
+ * gst-launch v4l2radio device=/dev/radio0 frequency=101200000
+ * gst-launch alsasrc device=hw:1 ! audioconvert ! audioresample ! alsasink
+ * ]|
+ * First pipeline tunes the radio device /dev/radio0 to station 101.2 MHz,
+ * second pipeline connects digital audio out (hw:1) to default sound card.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "gst/gst-i18n-plugin.h"
+
+#include "gstv4l2tuner.h"
+#include "gstv4l2radio.h"
+#include "v4l2_calls.h"
+
+GST_DEBUG_CATEGORY_STATIC (v4l2radio_debug);
+#define GST_CAT_DEFAULT v4l2radio_debug
+
+#define DEFAULT_PROP_DEVICE "/dev/radio0"
+#define MIN_FREQUENCY 87500000
+#define DEFAULT_FREQUENCY 100000000
+#define MAX_FREQUENCY 108000000
+
+enum
+{
+ ARG_0,
+ ARG_DEVICE,
+ ARG_FREQUENCY
+};
+
+static gboolean
+gst_v4l2radio_fill_channel_list (GstV4l2Radio * radio)
+{
+ int res;
+ struct v4l2_tuner vtun;
+ struct v4l2_capability vc;
+ GstV4l2TunerChannel *v4l2channel;
+ GstTunerChannel *channel;
+
+ GstElement *e;
+
+ GstV4l2Object *v4l2object;
+
+ e = GST_ELEMENT (radio);
+ v4l2object = radio->v4l2object;
+
+ GST_DEBUG_OBJECT (e, "getting audio enumeration");
+ GST_V4L2_CHECK_OPEN (v4l2object);
+
+ GST_DEBUG_OBJECT (e, " audio input");
+
+ memset (&vc, 0, sizeof (vc));
+
+ res = v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &vc);
+ if (res < 0)
+ goto caps_failed;
+
+ if (!(vc.capabilities & V4L2_CAP_TUNER))
+ goto not_a_tuner;
+
+ /* getting audio input */
+ memset (&vtun, 0, sizeof (vtun));
+ vtun.index = 0;
+
+ res = v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun);
+ if (res < 0)
+ goto tuner_failed;
+
+ GST_LOG_OBJECT (e, " index: %d", vtun.index);
+ GST_LOG_OBJECT (e, " name: '%s'", vtun.name);
+ GST_LOG_OBJECT (e, " type: %016x", (guint) vtun.type);
+ GST_LOG_OBJECT (e, " caps: %016x", (guint) vtun.capability);
+ GST_LOG_OBJECT (e, " rlow: %016x", (guint) vtun.rangelow);
+ GST_LOG_OBJECT (e, " rhigh: %016x", (guint) vtun.rangehigh);
+ GST_LOG_OBJECT (e, " audmode: %016x", (guint) vtun.audmode);
+
+ v4l2channel = g_object_new (GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
+ channel = GST_TUNER_CHANNEL (v4l2channel);
+ channel->label = g_strdup ((const gchar *) vtun.name);
+ channel->flags = GST_TUNER_CHANNEL_FREQUENCY | GST_TUNER_CHANNEL_AUDIO;
+ v4l2channel->index = 0;
+ v4l2channel->tuner = 0;
+
+ channel->freq_multiplicator =
+ 62.5 * ((vtun.capability & V4L2_TUNER_CAP_LOW) ? 1 : 1000);
+ channel->min_frequency = vtun.rangelow * channel->freq_multiplicator;
+ channel->max_frequency = vtun.rangehigh * channel->freq_multiplicator;
+ channel->min_signal = 0;
+ channel->max_signal = 0xffff;
+
+ v4l2object->channels =
+ g_list_prepend (v4l2object->channels, (gpointer) channel);
+
+ v4l2object->channels = g_list_reverse (v4l2object->channels);
+
+ GST_DEBUG_OBJECT (e, "done");
+ return TRUE;
+
+ /* ERRORS */
+tuner_failed:
+ {
+ GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
+ (_("Failed to get settings of tuner %d on device '%s'."),
+ vtun.index, v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+caps_failed:
+ {
+ GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
+ (_("Error getting capabilities for device '%s'."),
+ v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+not_a_tuner:
+ {
+ GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
+ (_("Device '%s' is not a tuner."),
+ v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_v4l2radio_get_input (GstV4l2Object * v4l2object, gint * input)
+{
+ GST_DEBUG_OBJECT (v4l2object->element, "trying to get radio input");
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ if (!v4l2object->channels)
+ goto input_failed;
+
+ *input = 0;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "input: %d", 0);
+
+ return TRUE;
+
+ /* ERRORS */
+input_failed:
+ {
+ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to get radio input on device '%s'. "),
+ v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_v4l2radio_set_input (GstV4l2Object * v4l2object, gint input)
+{
+ GST_DEBUG_OBJECT (v4l2object->element, "trying to set input to %d", input);
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ if (!v4l2object->channels)
+ goto input_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+input_failed:
+ {
+ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to set input %d on device %s."),
+ input, v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_v4l2radio_set_mute_on (GstV4l2Radio * radio, gboolean on)
+{
+ gint res;
+ struct v4l2_control vctrl;
+
+ GST_DEBUG_OBJECT (radio, "setting current tuner mute state: %d", on);
+
+ if (!GST_V4L2_IS_OPEN (radio->v4l2object))
+ return FALSE;
+
+ memset (&vctrl, 0, sizeof (vctrl));
+ vctrl.id = V4L2_CID_AUDIO_MUTE;
+ vctrl.value = on;
+
+ GST_DEBUG_OBJECT (radio, "radio fd: %d", radio->v4l2object->video_fd);
+
+ res = ioctl (radio->v4l2object->video_fd, VIDIOC_S_CTRL, &vctrl);
+ GST_DEBUG_OBJECT (radio, "mute state change result: %d", res);
+ if (res < 0)
+ goto freq_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+freq_failed:
+ {
+ GST_ELEMENT_WARNING (radio, RESOURCE, SETTINGS,
+ (_("Failed to change mute state for device '%s'."),
+ radio->v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_v4l2radio_set_mute (GstV4l2Radio * radio)
+{
+ return gst_v4l2radio_set_mute_on (radio, TRUE);
+}
+
+static gboolean
+gst_v4l2radio_set_unmute (GstV4l2Radio * radio)
+{
+ return gst_v4l2radio_set_mute_on (radio, FALSE);
+}
+
+GST_IMPLEMENT_V4L2_PROBE_METHODS (GstV4l2RadioClass, gst_v4l2radio);
+GST_IMPLEMENT_V4L2_TUNER_METHODS (GstV4l2Radio, gst_v4l2radio);
+
+static void gst_v4l2radio_uri_handler_init (gpointer g_iface,
+ gpointer iface_data);
+
+static gboolean
+gst_v4l2radio_interface_supported (GstImplementsInterface * iface,
+ GType iface_type)
+{
+ if (iface_type == GST_TYPE_TUNER)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+gst_v4l2radio_implements_interface_init (GstImplementsInterfaceClass * iface)
+{
+ iface->supported = gst_v4l2radio_interface_supported;
+}
+
+static void
+gst_v4l2radio_tuner_interface_reinit (GstTunerClass * iface)
+{
+ gst_v4l2radio_tuner_interface_init (iface);
+}
+
+static void
+gst_v4l2radio_interfaces (GType type)
+{
+ static const GInterfaceInfo urihandler_info = {
+ (GInterfaceInitFunc) gst_v4l2radio_uri_handler_init,
+ NULL,
+ NULL
+ };
+
+ static const GInterfaceInfo implements_interface_info = {
+ (GInterfaceInitFunc) gst_v4l2radio_implements_interface_init,
+ NULL,
+ NULL,
+ };
+
+ static const GInterfaceInfo propertyprobe_info = {
+ (GInterfaceInitFunc) gst_v4l2radio_property_probe_interface_init,
+ NULL,
+ NULL,
+ };
+
+ static const GInterfaceInfo tuner_interface_info = {
+ (GInterfaceInitFunc) gst_v4l2radio_tuner_interface_reinit,
+ NULL,
+ NULL,
+ };
+
+ g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info);
+ g_type_add_interface_static (type,
+ GST_TYPE_IMPLEMENTS_INTERFACE, &implements_interface_info);
+
+ g_type_add_interface_static (type, GST_TYPE_TUNER, &tuner_interface_info);
+
+ g_type_add_interface_static (type,
+ GST_TYPE_PROPERTY_PROBE, &propertyprobe_info);
+}
+
+GST_BOILERPLATE_FULL (GstV4l2Radio, gst_v4l2radio, GstElement, GST_TYPE_ELEMENT,
+ gst_v4l2radio_interfaces);
+
+static void gst_v4l2radio_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_v4l2radio_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static void gst_v4l2radio_finalize (GstV4l2Radio * radio);
+static void gst_v4l2radio_dispose (GObject * object);
+static GstStateChangeReturn gst_v4l2radio_change_state (GstElement * element,
+ GstStateChange transition);
+
+static void
+gst_v4l2radio_base_init (gpointer gclass)
+{
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (gclass);
+ GstV4l2RadioClass *gstv4l2radio_class = GST_V4L2RADIO_CLASS (gclass);
+
+ GST_DEBUG_CATEGORY_INIT (v4l2radio_debug, "v4l2radio", 0,
+ "V4l2 radio element");
+
+ gstv4l2radio_class->v4l2_class_devices = NULL;
+
+ gst_element_class_set_details_simple (gstelement_class,
+ "Radio (video4linux2) Tuner",
+ "Tuner",
+ "Controls a Video4Linux2 radio device",
+ "Alexey Chernov <4ernov@gmail.com>");
+}
+
+static void
+gst_v4l2radio_class_init (GstV4l2RadioClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+
+ gobject_class->set_property = gst_v4l2radio_set_property;
+ gobject_class->get_property = gst_v4l2radio_get_property;
+
+ g_object_class_install_property (gobject_class, ARG_DEVICE,
+ g_param_spec_string ("device", "Radio device location",
+ "Video4Linux2 radio device location",
+ DEFAULT_PROP_DEVICE, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, ARG_FREQUENCY,
+ g_param_spec_int ("frequency", "Station frequency",
+ "Station frequency in Hz",
+ MIN_FREQUENCY, MAX_FREQUENCY, DEFAULT_FREQUENCY, G_PARAM_READWRITE));
+
+ gobject_class->dispose = gst_v4l2radio_dispose;
+ gobject_class->finalize = (GObjectFinalizeFunc) gst_v4l2radio_finalize;
+
+ gstelement_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_v4l2radio_change_state);
+
+}
+
+static void
+gst_v4l2radio_init (GstV4l2Radio * filter, GstV4l2RadioClass * gclass)
+{
+ filter->v4l2object = gst_v4l2_object_new (GST_ELEMENT (filter),
+ V4L2_BUF_TYPE_VIDEO_CAPTURE, DEFAULT_PROP_DEVICE,
+ gst_v4l2radio_get_input, gst_v4l2radio_set_input, NULL);
+
+ filter->v4l2object->frequency = DEFAULT_FREQUENCY;
+ g_free (filter->v4l2object->videodev);
+ filter->v4l2object->videodev = g_strdup (DEFAULT_PROP_DEVICE);
+}
+
+static void
+gst_v4l2radio_dispose (GObject * object)
+{
+ GstV4l2Radio *radio = GST_V4L2RADIO (object);
+ gst_v4l2_close (radio->v4l2object);
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_v4l2radio_finalize (GstV4l2Radio * radio)
+{
+ gst_v4l2_object_destroy (radio->v4l2object);
+ G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (radio));
+}
+
+static gboolean
+gst_v4l2radio_open (GstV4l2Radio * radio)
+{
+ GstV4l2Object *v4l2object;
+
+ v4l2object = radio->v4l2object;
+ if (gst_v4l2_open (v4l2object))
+ return gst_v4l2radio_fill_channel_list (radio);
+ else
+ return FALSE;
+}
+
+static void
+gst_v4l2radio_set_defaults (GstV4l2Radio * radio)
+{
+ GstV4l2Object *v4l2object;
+ GstTunerChannel *channel = NULL;
+ GstTuner *tuner;
+
+ v4l2object = radio->v4l2object;
+
+ if (!GST_IS_TUNER (v4l2object->element))
+ return;
+
+ tuner = GST_TUNER (v4l2object->element);
+
+ if (v4l2object->channel)
+ channel = gst_tuner_find_channel_by_name (tuner, v4l2object->channel);
+ if (channel) {
+ gst_tuner_set_channel (tuner, channel);
+ } else {
+ channel =
+ GST_TUNER_CHANNEL (gst_tuner_get_channel (GST_TUNER
+ (v4l2object->element)));
+ if (channel) {
+ g_free (v4l2object->channel);
+ v4l2object->channel = g_strdup (channel->label);
+ gst_tuner_channel_changed (tuner, channel);
+ }
+ }
+
+ if (channel
+ && GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
+ if (v4l2object->frequency != 0) {
+ gst_tuner_set_frequency (tuner, channel, v4l2object->frequency);
+ } else {
+ v4l2object->frequency = gst_tuner_get_frequency (tuner, channel);
+ if (v4l2object->frequency == 0) {
+ /* guess */
+ gst_tuner_set_frequency (tuner, channel, MIN_FREQUENCY);
+ } else {
+ }
+ }
+ }
+}
+
+static gboolean
+gst_v4l2radio_start (GstV4l2Radio * radio)
+{
+ if (!gst_v4l2radio_open (radio))
+ return FALSE;
+
+ gst_v4l2radio_set_defaults (radio);
+
+ return TRUE;
+}
+
+static gboolean
+gst_v4l2radio_stop (GstV4l2Radio * radio)
+{
+ if (!gst_v4l2_object_stop (radio->v4l2object))
+ return FALSE;
+
+ return TRUE;
+}
+
+static GstStateChangeReturn
+gst_v4l2radio_change_state (GstElement * element, GstStateChange transition)
+{
+ GstV4l2Radio *radio;
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+ radio = GST_V4L2RADIO (element);
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ /*start radio */
+ if (!gst_v4l2radio_start (radio))
+ ret = GST_STATE_CHANGE_FAILURE;
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ /*unmute radio */
+ if (!gst_v4l2radio_set_unmute (radio))
+ ret = GST_STATE_CHANGE_FAILURE;
+ break;
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ /*mute radio */
+ if (!gst_v4l2radio_set_mute (radio))
+ ret = GST_STATE_CHANGE_FAILURE;
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ /*stop radio */
+ if (!gst_v4l2radio_stop (radio))
+ ret = GST_STATE_CHANGE_FAILURE;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static void
+gst_v4l2radio_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstV4l2Radio *radio = GST_V4L2RADIO (object);
+ gint frequency;
+ switch (prop_id) {
+ case ARG_DEVICE:
+ g_free (radio->v4l2object->videodev);
+ radio->v4l2object->videodev =
+ g_strdup ((gchar *) g_value_get_string (value));
+ break;
+ case ARG_FREQUENCY:
+ frequency = g_value_get_int (value);
+ if (frequency >= MIN_FREQUENCY && frequency <= MAX_FREQUENCY) {
+ radio->v4l2object->frequency = frequency;
+ gst_v4l2_set_frequency (radio->v4l2object, 0,
+ radio->v4l2object->frequency);
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_v4l2radio_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstV4l2Radio *radio = GST_V4L2RADIO (object);
+
+ switch (prop_id) {
+ case ARG_DEVICE:
+ g_value_set_string (value, radio->v4l2object->videodev);
+ break;
+ case ARG_FREQUENCY:
+ if (gst_v4l2_get_frequency (radio->v4l2object,
+ 0, &(radio->v4l2object->frequency)))
+ g_value_set_int (value, radio->v4l2object->frequency);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/* GstURIHandler interface */
+static GstURIType
+gst_v4l2radio_uri_get_type (void)
+{
+ return GST_URI_SRC;
+}
+
+static gchar **
+gst_v4l2radio_uri_get_protocols (void)
+{
+ static gchar *protocols[] = { (char *) "radio", NULL };
+ return protocols;
+}
+
+static const gchar *
+gst_v4l2radio_uri_get_uri (GstURIHandler * handler)
+{
+ GstV4l2Radio *radio = GST_V4L2RADIO (handler);
+
+ if (radio->v4l2object->videodev != NULL) {
+ if (gst_v4l2_get_frequency (radio->v4l2object,
+ 0, &(radio->v4l2object->frequency))) {
+ gchar uri[20];
+ gchar freq[6];
+ g_ascii_formatd (freq, 6, "%4.1f", radio->v4l2object->frequency / 1e6);
+ g_snprintf (uri, sizeof (uri), "radio://%s", freq);
+ return g_intern_string (uri);
+ }
+ }
+
+ return "radio://";
+}
+
+static gboolean
+gst_v4l2radio_uri_set_uri (GstURIHandler * handler, const gchar * uri)
+{
+ GstV4l2Radio *radio = GST_V4L2RADIO (handler);
+ gdouble dfreq;
+ gint ifreq;
+ const gchar *freq;
+ gchar *end;
+
+ if (strcmp (uri, "radio://") != 0) {
+ freq = uri + 8;
+
+ dfreq = g_ascii_strtod (freq, &end);
+
+ if (errno || strlen (end))
+ goto uri_failed;
+
+ ifreq = dfreq * 1e6;
+ g_object_set (radio, "frequency", ifreq, NULL);
+
+ } else
+ goto uri_failed;
+
+ return TRUE;
+
+uri_failed:
+ return FALSE;
+}
+
+static void
+gst_v4l2radio_uri_handler_init (gpointer g_iface, gpointer iface_data)
+{
+ GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
+
+ iface->get_type = gst_v4l2radio_uri_get_type;
+ iface->get_protocols = gst_v4l2radio_uri_get_protocols;
+ iface->get_uri = gst_v4l2radio_uri_get_uri;
+ iface->set_uri = gst_v4l2radio_uri_set_uri;
+}
diff --git a/sys/v4l2/gstv4l2radio.h b/sys/v4l2/gstv4l2radio.h
new file mode 100644
index 0000000..68b7ec3
--- /dev/null
+++ b/sys/v4l2/gstv4l2radio.h
@@ -0,0 +1,67 @@
+/* GStreamer v4l2 radio tuner element
+ * Copyright (C) 2010, 2011 Alexey Chernov <4ernov@gmail.com>
+ *
+ * gstv4l2radio.h - V4L2 radio tuner element
+ *
+ * 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.
+ */
+
+#ifndef __GST_V4L2RADIO_H__
+#define __GST_V4L2RADIO_H__
+
+#include "gstv4l2object.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_V4L2RADIO \
+ (gst_v4l2radio_get_type())
+#define GST_V4L2RADIO(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4L2RADIO,GstV4l2Radio))
+#define GST_V4L2RADIO_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4L2RADIO,GstV4l2RadioClass))
+#define GST_IS_V4L2RADIO(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4L2RADIO))
+#define GST_IS_V4L2RADIO_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4L2RADIO))
+
+typedef struct _GstV4l2Radio GstV4l2Radio;
+typedef struct _GstV4l2RadioClass GstV4l2RadioClass;
+
+/**
+ * GstV4l2Radio:
+ *
+ * Opaque video4linux2 radio tuner element
+ */
+struct _GstV4l2Radio
+{
+ GstElement element;
+
+ /*< private >*/
+ GstV4l2Object * v4l2object;
+};
+
+struct _GstV4l2RadioClass
+{
+ GstElementClass parent_class;
+
+ GList *v4l2_class_devices;
+};
+
+GType gst_v4l2radio_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_V4L2RADIO_H__ */
diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c
new file mode 100644
index 0000000..f6aba24
--- /dev/null
+++ b/sys/v4l2/gstv4l2sink.c
@@ -0,0 +1,971 @@
+/* GStreamer
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc - http://www.ti.com/
+ *
+ * Description: V4L2 sink element
+ * Created on: Jul 2, 2009
+ * Author: Rob Clark <rob@ti.com>
+ *
+ * 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-v4l2sink
+ *
+ * v4l2sink can be used to display video to v4l2 devices (screen overlays
+ * provided by the graphics hardware, tv-out, etc)
+ *
+ * <refsect2>
+ * <title>Example launch lines</title>
+ * |[
+ * gst-launch videotestsrc ! v4l2sink device=/dev/video1
+ * ]| This pipeline displays a test pattern on /dev/video1
+ * |[
+ * gst-launch -v videotestsrc ! navigationtest ! v4l2sink
+ * ]| A pipeline to test navigation events.
+ * While moving the mouse pointer over the test signal you will see a black box
+ * following the mouse pointer. If you press the mouse button somewhere on the
+ * video and release it somewhere else a green box will appear where you pressed
+ * the button and a red one where you released it. (The navigationtest element
+ * is part of gst-plugins-good.) You can observe here that even if the images
+ * are scaled through hardware the pointer coordinates are converted back to the
+ * original video frame geometry so that the box can be drawn to the correct
+ * position. This also handles borders correctly, limiting coordinates to the
+ * image area
+ * </refsect2>
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "gstv4l2colorbalance.h"
+#include "gstv4l2tuner.h"
+#ifdef HAVE_XVIDEO
+#include "gstv4l2xoverlay.h"
+#endif
+#include "gstv4l2vidorient.h"
+
+#include "gstv4l2sink.h"
+#include "gst/gst-i18n-plugin.h"
+
+#include <string.h>
+
+GST_DEBUG_CATEGORY (v4l2sink_debug);
+#define GST_CAT_DEFAULT v4l2sink_debug
+
+#define PROP_DEF_QUEUE_SIZE 12
+#define PROP_DEF_MIN_QUEUED_BUFS 1
+#define DEFAULT_PROP_DEVICE "/dev/video1"
+
+enum
+{
+ PROP_0,
+ V4L2_STD_OBJECT_PROPS,
+ PROP_QUEUE_SIZE,
+ PROP_MIN_QUEUED_BUFS,
+ PROP_OVERLAY_TOP,
+ PROP_OVERLAY_LEFT,
+ PROP_OVERLAY_WIDTH,
+ PROP_OVERLAY_HEIGHT,
+ PROP_CROP_TOP,
+ PROP_CROP_LEFT,
+ PROP_CROP_WIDTH,
+ PROP_CROP_HEIGHT,
+};
+
+
+GST_IMPLEMENT_V4L2_PROBE_METHODS (GstV4l2SinkClass, gst_v4l2sink);
+GST_IMPLEMENT_V4L2_COLOR_BALANCE_METHODS (GstV4l2Sink, gst_v4l2sink);
+GST_IMPLEMENT_V4L2_TUNER_METHODS (GstV4l2Sink, gst_v4l2sink);
+#ifdef HAVE_XVIDEO
+GST_IMPLEMENT_V4L2_XOVERLAY_METHODS (GstV4l2Sink, gst_v4l2sink);
+#endif
+GST_IMPLEMENT_V4L2_VIDORIENT_METHODS (GstV4l2Sink, gst_v4l2sink);
+
+static gboolean
+gst_v4l2sink_iface_supported (GstImplementsInterface * iface, GType iface_type)
+{
+ GstV4l2Object *v4l2object = GST_V4L2SINK (iface)->v4l2object;
+
+#ifdef HAVE_XVIDEO
+ g_assert (iface_type == GST_TYPE_X_OVERLAY ||
+ iface_type == GST_TYPE_NAVIGATION ||
+ iface_type == GST_TYPE_COLOR_BALANCE ||
+ iface_type == GST_TYPE_VIDEO_ORIENTATION ||
+ iface_type == GST_TYPE_TUNER);
+#else
+ g_assert (iface_type == GST_TYPE_COLOR_BALANCE ||
+ iface_type == GST_TYPE_VIDEO_ORIENTATION ||
+ iface_type == GST_TYPE_TUNER);
+#endif
+
+ if (v4l2object->video_fd == -1)
+ return FALSE;
+
+#ifdef HAVE_XVIDEO
+ if (!GST_V4L2_IS_OVERLAY (v4l2object)) {
+ if (iface_type == GST_TYPE_X_OVERLAY || iface_type == GST_TYPE_NAVIGATION)
+ return FALSE;
+ }
+#endif
+
+ return TRUE;
+}
+
+static void
+gst_v4l2sink_interface_init (GstImplementsInterfaceClass * klass)
+{
+ /*
+ * default virtual functions
+ */
+ klass->supported = gst_v4l2sink_iface_supported;
+}
+
+#ifdef HAVE_XVIDEO
+static void gst_v4l2sink_navigation_send_event (GstNavigation * navigation,
+ GstStructure * structure);
+static void
+gst_v4l2sink_navigation_init (GstNavigationInterface * iface)
+{
+ iface->send_event = gst_v4l2sink_navigation_send_event;
+}
+#endif
+
+static void
+gst_v4l2sink_init_interfaces (GType type)
+{
+ static const GInterfaceInfo v4l2iface_info = {
+ (GInterfaceInitFunc) gst_v4l2sink_interface_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo v4l2_tuner_info = {
+ (GInterfaceInitFunc) gst_v4l2sink_tuner_interface_init,
+ NULL,
+ NULL,
+ };
+#ifdef HAVE_XVIDEO
+ static const GInterfaceInfo v4l2_xoverlay_info = {
+ (GInterfaceInitFunc) gst_v4l2sink_xoverlay_interface_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo v4l2_navigation_info = {
+ (GInterfaceInitFunc) gst_v4l2sink_navigation_init,
+ NULL,
+ NULL,
+ };
+#endif
+ static const GInterfaceInfo v4l2_colorbalance_info = {
+ (GInterfaceInitFunc) gst_v4l2sink_color_balance_interface_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo v4l2_videoorientation_info = {
+ (GInterfaceInitFunc) gst_v4l2sink_video_orientation_interface_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo v4l2_propertyprobe_info = {
+ (GInterfaceInitFunc) gst_v4l2sink_property_probe_interface_init,
+ NULL,
+ NULL,
+ };
+
+ g_type_add_interface_static (type,
+ GST_TYPE_IMPLEMENTS_INTERFACE, &v4l2iface_info);
+ g_type_add_interface_static (type, GST_TYPE_TUNER, &v4l2_tuner_info);
+#ifdef HAVE_XVIDEO
+ g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &v4l2_xoverlay_info);
+ g_type_add_interface_static (type,
+ GST_TYPE_NAVIGATION, &v4l2_navigation_info);
+#endif
+ g_type_add_interface_static (type,
+ GST_TYPE_COLOR_BALANCE, &v4l2_colorbalance_info);
+ g_type_add_interface_static (type,
+ GST_TYPE_VIDEO_ORIENTATION, &v4l2_videoorientation_info);
+ g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
+ &v4l2_propertyprobe_info);
+}
+
+
+GST_BOILERPLATE_FULL (GstV4l2Sink, gst_v4l2sink, GstVideoSink,
+ GST_TYPE_VIDEO_SINK, gst_v4l2sink_init_interfaces);
+
+
+static void gst_v4l2sink_dispose (GObject * object);
+static void gst_v4l2sink_finalize (GstV4l2Sink * v4l2sink);
+
+/* GObject methods: */
+static void gst_v4l2sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_v4l2sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+
+/* GstElement methods: */
+static GstStateChangeReturn gst_v4l2sink_change_state (GstElement * element,
+ GstStateChange transition);
+
+/* GstBaseSink methods: */
+static GstCaps *gst_v4l2sink_get_caps (GstBaseSink * bsink);
+static gboolean gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps);
+static GstFlowReturn gst_v4l2sink_buffer_alloc (GstBaseSink * bsink,
+ guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
+static GstFlowReturn gst_v4l2sink_show_frame (GstBaseSink * bsink,
+ GstBuffer * buf);
+
+static void
+gst_v4l2sink_base_init (gpointer g_class)
+{
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+ GstV4l2SinkClass *gstv4l2sink_class = GST_V4L2SINK_CLASS (g_class);
+ GstPadTemplate *pad_template;
+
+ gstv4l2sink_class->v4l2_class_devices = NULL;
+
+ GST_DEBUG_CATEGORY_INIT (v4l2sink_debug, "v4l2sink", 0, "V4L2 sink element");
+
+ gst_element_class_set_details_simple (gstelement_class,
+ "Video (video4linux2) Sink", "Sink/Video",
+ "Displays frames on a video4linux2 device", "Rob Clark <rob@ti.com>,");
+
+ pad_template =
+ gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+ gst_v4l2_object_get_all_caps ());
+ gst_element_class_add_pad_template (gstelement_class, pad_template);
+ gst_object_unref (pad_template);
+}
+
+static void
+gst_v4l2sink_class_init (GstV4l2SinkClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *element_class;
+ GstBaseSinkClass *basesink_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ element_class = GST_ELEMENT_CLASS (klass);
+ basesink_class = GST_BASE_SINK_CLASS (klass);
+
+ gobject_class->dispose = gst_v4l2sink_dispose;
+ gobject_class->finalize = (GObjectFinalizeFunc) gst_v4l2sink_finalize;
+ gobject_class->set_property = gst_v4l2sink_set_property;
+ gobject_class->get_property = gst_v4l2sink_get_property;
+
+ element_class->change_state = gst_v4l2sink_change_state;
+
+ gst_v4l2_object_install_properties_helper (gobject_class,
+ DEFAULT_PROP_DEVICE);
+ g_object_class_install_property (gobject_class, PROP_QUEUE_SIZE,
+ g_param_spec_uint ("queue-size", "Queue size",
+ "Number of buffers to be enqueud in the driver in streaming mode",
+ GST_V4L2_MIN_BUFFERS, GST_V4L2_MAX_BUFFERS, PROP_DEF_QUEUE_SIZE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_MIN_QUEUED_BUFS,
+ g_param_spec_uint ("min-queued-bufs", "Minimum queued bufs",
+ "Minimum number of queued bufs; v4l2sink won't dqbuf if the driver "
+ "doesn't have more than this number (which normally you shouldn't change)",
+ 0, GST_V4L2_MAX_BUFFERS, PROP_DEF_MIN_QUEUED_BUFS,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_OVERLAY_TOP,
+ g_param_spec_int ("overlay-top", "Overlay top",
+ "The topmost (y) coordinate of the video overlay; top left corner of screen is 0,0",
+ G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_OVERLAY_LEFT,
+ g_param_spec_int ("overlay-left", "Overlay left",
+ "The leftmost (x) coordinate of the video overlay; top left corner of screen is 0,0",
+ G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_OVERLAY_WIDTH,
+ g_param_spec_uint ("overlay-width", "Overlay width",
+ "The width of the video overlay; default is equal to negotiated image width",
+ 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_OVERLAY_HEIGHT,
+ g_param_spec_uint ("overlay-height", "Overlay height",
+ "The height of the video overlay; default is equal to negotiated image height",
+ 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_CROP_TOP,
+ g_param_spec_int ("crop-top", "Crop top",
+ "The topmost (y) coordinate of the video crop; top left corner of image is 0,0",
+ 0x80000000, 0x7fffffff, 0, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, PROP_CROP_LEFT,
+ g_param_spec_int ("crop-left", "Crop left",
+ "The leftmost (x) coordinate of the video crop; top left corner of image is 0,0",
+ 0x80000000, 0x7fffffff, 0, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, PROP_CROP_WIDTH,
+ g_param_spec_uint ("crop-width", "Crop width",
+ "The width of the video crop; default is equal to negotiated image width",
+ 0, 0xffffffff, 0, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, PROP_CROP_HEIGHT,
+ g_param_spec_uint ("crop-height", "Crop height",
+ "The height of the video crop; default is equal to negotiated image height",
+ 0, 0xffffffff, 0, G_PARAM_READWRITE));
+
+ basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2sink_get_caps);
+ basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2sink_set_caps);
+ basesink_class->buffer_alloc = GST_DEBUG_FUNCPTR (gst_v4l2sink_buffer_alloc);
+ basesink_class->render = GST_DEBUG_FUNCPTR (gst_v4l2sink_show_frame);
+}
+
+static void
+gst_v4l2sink_init (GstV4l2Sink * v4l2sink, GstV4l2SinkClass * klass)
+{
+ v4l2sink->v4l2object = gst_v4l2_object_new (GST_ELEMENT (v4l2sink),
+ V4L2_BUF_TYPE_VIDEO_OUTPUT, DEFAULT_PROP_DEVICE,
+ gst_v4l2_get_output, gst_v4l2_set_output, NULL);
+
+ /* same default value for video output device as is used for
+ * v4l2src/capture is no good.. so lets set a saner default
+ * (which can be overridden by the one creating the v4l2sink
+ * after the constructor returns)
+ */
+ g_object_set (v4l2sink, "device", "/dev/video1", NULL);
+
+ /* number of buffers requested */
+ v4l2sink->num_buffers = PROP_DEF_QUEUE_SIZE;
+ v4l2sink->min_queued_bufs = PROP_DEF_MIN_QUEUED_BUFS;
+
+ v4l2sink->probed_caps = NULL;
+ v4l2sink->current_caps = NULL;
+
+ v4l2sink->overlay_fields_set = 0;
+ v4l2sink->crop_fields_set = 0;
+ v4l2sink->state = 0;
+}
+
+
+static void
+gst_v4l2sink_dispose (GObject * object)
+{
+ GstV4l2Sink *v4l2sink = GST_V4L2SINK (object);
+
+ if (v4l2sink->probed_caps) {
+ gst_caps_unref (v4l2sink->probed_caps);
+ }
+
+ if (v4l2sink->current_caps) {
+ gst_caps_unref (v4l2sink->current_caps);
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+
+static void
+gst_v4l2sink_finalize (GstV4l2Sink * v4l2sink)
+{
+ gst_v4l2_object_destroy (v4l2sink->v4l2object);
+
+ G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (v4l2sink));
+}
+
+
+/*
+ * State values
+ */
+enum
+{
+ STATE_OFF = 0,
+ STATE_PENDING_STREAMON,
+ STATE_STREAMING
+};
+
+/*
+ * flags to indicate which overlay/crop properties the user has set (and
+ * therefore which ones should override the defaults from the driver)
+ */
+enum
+{
+ RECT_TOP_SET = 0x01,
+ RECT_LEFT_SET = 0x02,
+ RECT_WIDTH_SET = 0x04,
+ RECT_HEIGHT_SET = 0x08
+};
+
+static void
+gst_v4l2sink_sync_overlay_fields (GstV4l2Sink * v4l2sink)
+{
+ if (!v4l2sink->overlay_fields_set)
+ return;
+
+ if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) {
+
+ gint fd = v4l2sink->v4l2object->video_fd;
+ struct v4l2_format format;
+
+ memset (&format, 0x00, sizeof (struct v4l2_format));
+ format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+
+ if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0) {
+ GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_FMT failed");
+ return;
+ }
+
+ GST_DEBUG_OBJECT (v4l2sink,
+ "setting overlay: overlay_fields_set=0x%02x, top=%d, left=%d, width=%d, height=%d",
+ v4l2sink->overlay_fields_set,
+ v4l2sink->overlay.top, v4l2sink->overlay.left,
+ v4l2sink->overlay.width, v4l2sink->overlay.height);
+
+ if (v4l2sink->overlay_fields_set & RECT_TOP_SET)
+ format.fmt.win.w.top = v4l2sink->overlay.top;
+ if (v4l2sink->overlay_fields_set & RECT_LEFT_SET)
+ format.fmt.win.w.left = v4l2sink->overlay.left;
+ if (v4l2sink->overlay_fields_set & RECT_WIDTH_SET)
+ format.fmt.win.w.width = v4l2sink->overlay.width;
+ if (v4l2sink->overlay_fields_set & RECT_HEIGHT_SET)
+ format.fmt.win.w.height = v4l2sink->overlay.height;
+
+ if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
+ GST_WARNING_OBJECT (v4l2sink, "VIDIOC_S_FMT failed");
+ return;
+ }
+
+ v4l2sink->overlay_fields_set = 0;
+ v4l2sink->overlay = format.fmt.win.w;
+ }
+}
+
+static void
+gst_v4l2sink_sync_crop_fields (GstV4l2Sink * v4l2sink)
+{
+ if (!v4l2sink->crop_fields_set)
+ return;
+
+ if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) {
+
+ gint fd = v4l2sink->v4l2object->video_fd;
+ struct v4l2_crop crop;
+
+ memset (&crop, 0x00, sizeof (struct v4l2_crop));
+ crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
+ if (v4l2_ioctl (fd, VIDIOC_G_CROP, &crop) < 0) {
+ GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_CROP failed");
+ return;
+ }
+
+ GST_DEBUG_OBJECT (v4l2sink,
+ "setting crop: crop_fields_set=0x%02x, top=%d, left=%d, width=%d, height=%d",
+ v4l2sink->crop_fields_set,
+ v4l2sink->crop.top, v4l2sink->crop.left,
+ v4l2sink->crop.width, v4l2sink->crop.height);
+
+ if (v4l2sink->crop_fields_set & RECT_TOP_SET)
+ crop.c.top = v4l2sink->crop.top;
+ if (v4l2sink->crop_fields_set & RECT_LEFT_SET)
+ crop.c.left = v4l2sink->crop.left;
+ if (v4l2sink->crop_fields_set & RECT_WIDTH_SET)
+ crop.c.width = v4l2sink->crop.width;
+ if (v4l2sink->crop_fields_set & RECT_HEIGHT_SET)
+ crop.c.height = v4l2sink->crop.height;
+
+ if (v4l2_ioctl (fd, VIDIOC_S_CROP, &crop) < 0) {
+ GST_WARNING_OBJECT (v4l2sink, "VIDIOC_S_CROP failed");
+ return;
+ }
+
+ v4l2sink->crop_fields_set = 0;
+ v4l2sink->crop = crop.c;
+ }
+}
+
+
+static void
+gst_v4l2sink_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ GstV4l2Sink *v4l2sink = GST_V4L2SINK (object);
+
+ if (!gst_v4l2_object_set_property_helper (v4l2sink->v4l2object,
+ prop_id, value, pspec)) {
+ switch (prop_id) {
+ case PROP_QUEUE_SIZE:
+ v4l2sink->num_buffers = g_value_get_uint (value);
+ break;
+ case PROP_MIN_QUEUED_BUFS:
+ v4l2sink->min_queued_bufs = g_value_get_uint (value);
+ break;
+ case PROP_OVERLAY_TOP:
+ v4l2sink->overlay.top = g_value_get_int (value);
+ v4l2sink->overlay_fields_set |= RECT_TOP_SET;
+ gst_v4l2sink_sync_overlay_fields (v4l2sink);
+ break;
+ case PROP_OVERLAY_LEFT:
+ v4l2sink->overlay.left = g_value_get_int (value);
+ v4l2sink->overlay_fields_set |= RECT_LEFT_SET;
+ gst_v4l2sink_sync_overlay_fields (v4l2sink);
+ break;
+ case PROP_OVERLAY_WIDTH:
+ v4l2sink->overlay.width = g_value_get_uint (value);
+ v4l2sink->overlay_fields_set |= RECT_WIDTH_SET;
+ gst_v4l2sink_sync_overlay_fields (v4l2sink);
+ break;
+ case PROP_OVERLAY_HEIGHT:
+ v4l2sink->overlay.height = g_value_get_uint (value);
+ v4l2sink->overlay_fields_set |= RECT_HEIGHT_SET;
+ gst_v4l2sink_sync_overlay_fields (v4l2sink);
+ break;
+ case PROP_CROP_TOP:
+ v4l2sink->crop.top = g_value_get_int (value);
+ v4l2sink->crop_fields_set |= RECT_TOP_SET;
+ gst_v4l2sink_sync_crop_fields (v4l2sink);
+ break;
+ case PROP_CROP_LEFT:
+ v4l2sink->crop.left = g_value_get_int (value);
+ v4l2sink->crop_fields_set |= RECT_LEFT_SET;
+ gst_v4l2sink_sync_crop_fields (v4l2sink);
+ break;
+ case PROP_CROP_WIDTH:
+ v4l2sink->crop.width = g_value_get_uint (value);
+ v4l2sink->crop_fields_set |= RECT_WIDTH_SET;
+ gst_v4l2sink_sync_crop_fields (v4l2sink);
+ break;
+ case PROP_CROP_HEIGHT:
+ v4l2sink->crop.height = g_value_get_uint (value);
+ v4l2sink->crop_fields_set |= RECT_HEIGHT_SET;
+ gst_v4l2sink_sync_crop_fields (v4l2sink);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ }
+}
+
+
+static void
+gst_v4l2sink_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ GstV4l2Sink *v4l2sink = GST_V4L2SINK (object);
+
+ if (!gst_v4l2_object_get_property_helper (v4l2sink->v4l2object,
+ prop_id, value, pspec)) {
+ switch (prop_id) {
+ case PROP_QUEUE_SIZE:
+ g_value_set_uint (value, v4l2sink->num_buffers);
+ break;
+ case PROP_MIN_QUEUED_BUFS:
+ g_value_set_uint (value, v4l2sink->min_queued_bufs);
+ break;
+ case PROP_OVERLAY_TOP:
+ g_value_set_int (value, v4l2sink->overlay.top);
+ break;
+ case PROP_OVERLAY_LEFT:
+ g_value_set_int (value, v4l2sink->overlay.left);
+ break;
+ case PROP_OVERLAY_WIDTH:
+ g_value_set_uint (value, v4l2sink->overlay.width);
+ break;
+ case PROP_OVERLAY_HEIGHT:
+ g_value_set_uint (value, v4l2sink->overlay.height);
+ break;
+ case PROP_CROP_TOP:
+ g_value_set_int (value, v4l2sink->crop.top);
+ break;
+ case PROP_CROP_LEFT:
+ g_value_set_int (value, v4l2sink->crop.left);
+ break;
+ case PROP_CROP_WIDTH:
+ g_value_set_uint (value, v4l2sink->crop.width);
+ break;
+ case PROP_CROP_HEIGHT:
+ g_value_set_uint (value, v4l2sink->crop.height);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ }
+}
+
+static GstStateChangeReturn
+gst_v4l2sink_change_state (GstElement * element, GstStateChange transition)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ GstV4l2Sink *v4l2sink = GST_V4L2SINK (element);
+
+ GST_DEBUG_OBJECT (v4l2sink, "%d -> %d",
+ GST_STATE_TRANSITION_CURRENT (transition),
+ GST_STATE_TRANSITION_NEXT (transition));
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ /* open the device */
+ if (!gst_v4l2_object_start (v4l2sink->v4l2object))
+ return GST_STATE_CHANGE_FAILURE;
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ if (v4l2sink->state == STATE_STREAMING) {
+ if (!gst_v4l2_object_stop_streaming (v4l2sink->v4l2object)) {
+ return GST_STATE_CHANGE_FAILURE;
+ }
+ v4l2sink->state = STATE_PENDING_STREAMON;
+ }
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ if (NULL != v4l2sink->pool)
+ gst_v4l2_buffer_pool_destroy (v4l2sink->pool);
+ v4l2sink->pool = NULL;
+ /* close the device */
+ if (!gst_v4l2_object_stop (v4l2sink->v4l2object))
+ return GST_STATE_CHANGE_FAILURE;
+ v4l2sink->state = STATE_OFF;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+
+static GstCaps *
+gst_v4l2sink_get_caps (GstBaseSink * bsink)
+{
+ GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink);
+ GstCaps *ret;
+ GSList *walk;
+ GSList *formats;
+
+ if (!GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) {
+ /* FIXME: copy? */
+ GST_DEBUG_OBJECT (v4l2sink, "device is not open");
+ return
+ gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD
+ (v4l2sink)));
+ }
+
+ if (v4l2sink->probed_caps) {
+ LOG_CAPS (v4l2sink, v4l2sink->probed_caps);
+ return gst_caps_ref (v4l2sink->probed_caps);
+ }
+
+ formats = gst_v4l2_object_get_format_list (v4l2sink->v4l2object);
+
+ ret = gst_caps_new_empty ();
+
+ for (walk = formats; walk; walk = walk->next) {
+ struct v4l2_fmtdesc *format;
+
+ GstStructure *template;
+
+ format = (struct v4l2_fmtdesc *) walk->data;
+
+ template = gst_v4l2_object_v4l2fourcc_to_structure (format->pixelformat);
+
+ if (template) {
+ GstCaps *tmp;
+
+ tmp =
+ gst_v4l2_object_probe_caps_for_format (v4l2sink->v4l2object,
+ format->pixelformat, template);
+ if (tmp)
+ gst_caps_append (ret, tmp);
+
+ gst_structure_free (template);
+ } else {
+ GST_DEBUG_OBJECT (v4l2sink, "unknown format %u", format->pixelformat);
+ }
+ }
+
+ v4l2sink->probed_caps = gst_caps_ref (ret);
+
+ GST_INFO_OBJECT (v4l2sink, "probed caps: %p", ret);
+ LOG_CAPS (v4l2sink, ret);
+
+ return ret;
+}
+
+static gboolean
+gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
+{
+ GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink);
+ gint w = 0, h = 0;
+ gboolean interlaced;
+ struct v4l2_fmtdesc *format;
+ guint fps_n, fps_d;
+ guint size;
+
+ LOG_CAPS (v4l2sink, caps);
+
+ if (!GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) {
+ GST_DEBUG_OBJECT (v4l2sink, "device is not open");
+ return FALSE;
+ }
+
+ if (v4l2sink->current_caps) {
+ GST_DEBUG_OBJECT (v4l2sink, "already have caps set.. are they equal?");
+ LOG_CAPS (v4l2sink, v4l2sink->current_caps);
+ if (gst_caps_is_equal (v4l2sink->current_caps, caps)) {
+ GST_DEBUG_OBJECT (v4l2sink, "yes they are!");
+ return TRUE;
+ }
+ GST_DEBUG_OBJECT (v4l2sink, "no they aren't!");
+ }
+
+ if (v4l2sink->pool) {
+ /* TODO: if we've already allocated buffers, we probably need to
+ * do something here to free and reallocate....
+ *
+ * gst_v4l2_object_stop_streaming()
+ * gst_v4l2_buffer_pool_destroy()
+ *
+ */
+ GST_DEBUG_OBJECT (v4l2sink, "warning, changing caps not supported yet");
+ return FALSE;
+ }
+
+ /* we want our own v4l2 type of fourcc codes */
+ if (!gst_v4l2_object_get_caps_info (v4l2sink->v4l2object, caps,
+ &format, &w, &h, &interlaced, &fps_n, &fps_d, &size)) {
+ GST_DEBUG_OBJECT (v4l2sink, "can't get capture format from caps %p", caps);
+ return FALSE;
+ }
+
+ if (!format) {
+ GST_DEBUG_OBJECT (v4l2sink, "unrecognized caps!!");
+ return FALSE;
+ }
+
+ if (!gst_v4l2_object_set_format (v4l2sink->v4l2object, format->pixelformat,
+ w, h, interlaced)) {
+ /* error already posted */
+ return FALSE;
+ }
+
+ v4l2sink->video_width = w;
+ v4l2sink->video_height = h;
+
+ /* TODO: videosink width/height should be scaled according to
+ * pixel-aspect-ratio
+ */
+ GST_VIDEO_SINK_WIDTH (v4l2sink) = w;
+ GST_VIDEO_SINK_HEIGHT (v4l2sink) = h;
+
+ v4l2sink->current_caps = gst_caps_ref (caps);
+
+ return TRUE;
+}
+
+/* buffer alloc function to implement pad_alloc for upstream element */
+static GstFlowReturn
+gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
+ GstCaps * caps, GstBuffer ** buf)
+{
+ GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink);
+ GstV4l2Buffer *v4l2buf;
+
+ if (v4l2sink->v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
+
+ /* initialize the buffer pool if not initialized yet (first buffer): */
+ if (G_UNLIKELY (!v4l2sink->pool)) {
+
+ /* set_caps() might not be called yet.. so just to make sure: */
+ if (!gst_v4l2sink_set_caps (bsink, caps)) {
+ return GST_FLOW_ERROR;
+ }
+
+ GST_V4L2_CHECK_OPEN (v4l2sink->v4l2object);
+
+ if (!(v4l2sink->pool = gst_v4l2_buffer_pool_new (GST_ELEMENT (v4l2sink),
+ v4l2sink->v4l2object->video_fd,
+ v4l2sink->num_buffers, caps, FALSE,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT))) {
+ return GST_FLOW_ERROR;
+ }
+
+ gst_v4l2sink_sync_overlay_fields (v4l2sink);
+ gst_v4l2sink_sync_crop_fields (v4l2sink);
+
+#ifdef HAVE_XVIDEO
+ gst_v4l2_xoverlay_prepare_xwindow_id (v4l2sink->v4l2object, TRUE);
+#endif
+
+ v4l2sink->state = STATE_PENDING_STREAMON;
+
+ GST_INFO_OBJECT (v4l2sink, "outputting buffers via mmap()");
+
+ if (v4l2sink->num_buffers != v4l2sink->pool->buffer_count) {
+ v4l2sink->num_buffers = v4l2sink->pool->buffer_count;
+ g_object_notify (G_OBJECT (v4l2sink), "queue-size");
+ }
+ }
+
+ v4l2buf = gst_v4l2_buffer_pool_get (v4l2sink->pool, TRUE);
+
+ if (G_LIKELY (v4l2buf)) {
+ GST_DEBUG_OBJECT (v4l2sink, "allocated buffer: %p", v4l2buf);
+ *buf = GST_BUFFER (v4l2buf);
+ return GST_FLOW_OK;
+ } else {
+ GST_DEBUG_OBJECT (v4l2sink, "failed to allocate buffer");
+ return GST_FLOW_ERROR;
+ }
+
+ } else {
+ GST_ERROR_OBJECT (v4l2sink, "only supporting streaming mode for now...");
+ return GST_FLOW_ERROR;
+ }
+}
+
+/* called after A/V sync to render frame */
+static GstFlowReturn
+gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
+{
+ GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink);
+ GstBuffer *newbuf = NULL;
+
+ GST_DEBUG_OBJECT (v4l2sink, "render buffer: %p", buf);
+
+ if (!GST_IS_V4L2_BUFFER (buf)) {
+ GstFlowReturn ret;
+
+ /* special case check for sub-buffers: In certain cases, places like
+ * GstBaseTransform, which might check that the buffer is writable
+ * before copying metadata, timestamp, and such, will find that the
+ * buffer has more than one reference to it. In these cases, they
+ * will create a sub-buffer with an offset=0 and length equal to the
+ * original buffer size.
+ *
+ * This could happen in two scenarios: (1) a tee in the pipeline, and
+ * (2) because the refcnt is incremented in gst_mini_object_free()
+ * before the finalize function is called, and decremented after it
+ * returns.. but returning this buffer to the buffer pool in the
+ * finalize function, could wake up a thread blocked in _buffer_alloc()
+ * which could run and get a buffer w/ refcnt==2 before the thread
+ * originally unref'ing the buffer returns from finalize function and
+ * decrements the refcnt back to 1!
+ */
+ if (buf->parent &&
+ (GST_BUFFER_DATA (buf) == GST_BUFFER_DATA (buf->parent)) &&
+ (GST_BUFFER_SIZE (buf) == GST_BUFFER_SIZE (buf->parent))) {
+ GST_DEBUG_OBJECT (v4l2sink, "I have a sub-buffer!");
+ return gst_v4l2sink_show_frame (bsink, buf->parent);
+ }
+
+ GST_DEBUG_OBJECT (v4l2sink, "slow-path.. I got a %s so I need to memcpy",
+ g_type_name (G_OBJECT_TYPE (buf)));
+
+ ret = gst_v4l2sink_buffer_alloc (bsink,
+ GST_BUFFER_OFFSET (buf), GST_BUFFER_SIZE (buf), GST_BUFFER_CAPS (buf),
+ &newbuf);
+
+ if (GST_FLOW_OK != ret) {
+ GST_DEBUG_OBJECT (v4l2sink,
+ "dropping frame! Consider increasing 'queue-size' property!");
+ return GST_FLOW_OK;
+ }
+
+ memcpy (GST_BUFFER_DATA (newbuf),
+ GST_BUFFER_DATA (buf),
+ MIN (GST_BUFFER_SIZE (newbuf), GST_BUFFER_SIZE (buf)));
+
+ GST_DEBUG_OBJECT (v4l2sink, "render copied buffer: %p", newbuf);
+
+ buf = newbuf;
+ }
+
+ if (!gst_v4l2_buffer_pool_qbuf (v4l2sink->pool, GST_V4L2_BUFFER (buf))) {
+ return GST_FLOW_ERROR;
+ }
+ if (v4l2sink->state == STATE_PENDING_STREAMON) {
+ if (!gst_v4l2_object_start_streaming (v4l2sink->v4l2object)) {
+ return GST_FLOW_ERROR;
+ }
+ v4l2sink->state = STATE_STREAMING;
+ }
+
+ if (!newbuf) {
+ gst_buffer_ref (buf);
+ }
+
+ /* if the driver has more than one buffer, ie. more than just the one we
+ * just queued, then dequeue one immediately to make it available via
+ * _buffer_alloc():
+ */
+ if (gst_v4l2_buffer_pool_available_buffers (v4l2sink->pool) >
+ v4l2sink->min_queued_bufs) {
+ GstV4l2Buffer *v4l2buf = gst_v4l2_buffer_pool_dqbuf (v4l2sink->pool);
+
+ /* note: if we get a buf, we don't want to use it directly (because
+ * someone else could still hold a ref).. but instead we release our
+ * reference to it, and if no one else holds a ref it will be returned
+ * to the pool of available buffers.. and if not, we keep looping.
+ */
+ if (v4l2buf) {
+ gst_buffer_unref (GST_BUFFER (v4l2buf));
+ }
+ }
+
+ return GST_FLOW_OK;
+}
+
+#ifdef HAVE_XVIDEO
+static void
+gst_v4l2sink_navigation_send_event (GstNavigation * navigation,
+ GstStructure * structure)
+{
+ GstV4l2Sink *v4l2sink = GST_V4L2SINK (navigation);
+ GstV4l2Xv *xv = v4l2sink->v4l2object->xv;
+ GstPad *peer;
+
+ if (!xv)
+ return;
+
+ if ((peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (v4l2sink)))) {
+ GstVideoRectangle rect;
+ gdouble x, y, xscale = 1.0, yscale = 1.0;
+
+ gst_v4l2_xoverlay_get_render_rect (v4l2sink->v4l2object, &rect);
+
+ /* We calculate scaling using the original video frames geometry to
+ * include pixel aspect ratio scaling.
+ */
+ xscale = (gdouble) v4l2sink->video_width / rect.w;
+ yscale = (gdouble) v4l2sink->video_height / rect.h;
+
+ /* Converting pointer coordinates to the non scaled geometry */
+ if (gst_structure_get_double (structure, "pointer_x", &x)) {
+ x = MIN (x, rect.x + rect.w);
+ x = MAX (x - rect.x, 0);
+ gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
+ (gdouble) x * xscale, NULL);
+ }
+ if (gst_structure_get_double (structure, "pointer_y", &y)) {
+ y = MIN (y, rect.y + rect.h);
+ y = MAX (y - rect.y, 0);
+ gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
+ (gdouble) y * yscale, NULL);
+ }
+
+ gst_pad_send_event (peer, gst_event_new_navigation (structure));
+ gst_object_unref (peer);
+ }
+}
+#endif
diff --git a/sys/v4l2/gstv4l2sink.h b/sys/v4l2/gstv4l2sink.h
new file mode 100644
index 0000000..8fe8222
--- /dev/null
+++ b/sys/v4l2/gstv4l2sink.h
@@ -0,0 +1,91 @@
+/* GStreamer
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc - http://www.ti.com/
+ *
+ * Description: V4L2 sink element
+ * Created on: Jul 2, 2009
+ * Author: Rob Clark <rob@ti.com>
+ *
+ * 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.
+ */
+
+#ifndef __GSTV4L2SINK_H__
+#define __GSTV4L2SINK_H__
+
+#include <gst/video/gstvideosink.h>
+#include <gstv4l2object.h>
+#include <gstv4l2bufferpool.h>
+
+GST_DEBUG_CATEGORY_EXTERN (v4l2sink_debug);
+
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_V4L2SINK \
+ (gst_v4l2sink_get_type())
+#define GST_V4L2SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_V4L2SINK, GstV4l2Sink))
+#define GST_V4L2SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_V4L2SINK, GstV4l2SinkClass))
+#define GST_IS_V4L2SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_V4L2SINK))
+#define GST_IS_V4L2SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_V4L2SINK))
+
+typedef struct _GstV4l2Sink GstV4l2Sink;
+typedef struct _GstV4l2SinkClass GstV4l2SinkClass;
+
+
+struct _GstV4l2Sink {
+ GstVideoSink videosink;
+
+ /*< private >*/
+ GstV4l2Object * v4l2object;
+ GstCaps *probed_caps; /* all supported caps of underlying v4l2 device */
+ GstCaps *current_caps; /* the current negotiated caps */
+ GstV4l2BufferPool *pool;
+ guint32 num_buffers;
+ guint32 min_queued_bufs;
+
+ gint video_width, video_height; /* original (unscaled) video w/h */
+
+ /*
+ * field to store requested overlay and crop top/left/width/height props:
+ * note, could maybe be combined with 'vwin' field in GstV4l2Object?
+ */
+ struct v4l2_rect overlay, crop;
+
+ /*
+ * bitmask to track which overlay and crop fields user has requested by
+ * setting properties:
+ */
+ guint8 overlay_fields_set, crop_fields_set;
+
+ guint8 state;
+};
+
+struct _GstV4l2SinkClass {
+ GstVideoSinkClass parent_class;
+
+ GList *v4l2_class_devices;
+};
+
+GType gst_v4l2sink_get_type(void);
+
+G_END_DECLS
+
+
+#endif /* __GSTV4L2SINK_H__ */
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
new file mode 100644
index 0000000..f8ae09c
--- /dev/null
+++ b/sys/v4l2/gstv4l2src.c
@@ -0,0 +1,1072 @@
+/* GStreamer
+ *
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2src.c: Video4Linux2 source element
+ *
+ * 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-v4l2src
+ *
+ * v4l2src can be used to capture video from v4l2 devices, like webcams and tv
+ * cards.
+ *
+ * <refsect2>
+ * <title>Example launch lines</title>
+ * |[
+ * gst-launch v4l2src ! xvimagesink
+ * ]| This pipeline shows the video captured from /dev/video0 tv card and for
+ * webcams.
+ * |[
+ * gst-launch v4l2src ! jpegdec ! xvimagesink
+ * ]| This pipeline shows the video captured from a webcam that delivers jpeg
+ * images.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#undef HAVE_XVIDEO
+
+#include <string.h>
+#include <sys/time.h>
+#include "v4l2src_calls.h"
+#include <unistd.h>
+
+#include "gstv4l2colorbalance.h"
+#include "gstv4l2tuner.h"
+#ifdef HAVE_XVIDEO
+#include "gstv4l2xoverlay.h"
+#endif
+#include "gstv4l2vidorient.h"
+
+#include "gst/gst-i18n-plugin.h"
+
+GST_DEBUG_CATEGORY (v4l2src_debug);
+#define GST_CAT_DEFAULT v4l2src_debug
+
+#define PROP_DEF_QUEUE_SIZE 2
+#define PROP_DEF_ALWAYS_COPY TRUE
+#define PROP_DEF_DECIMATE 1
+
+#define DEFAULT_PROP_DEVICE "/dev/video0"
+
+enum
+{
+ PROP_0,
+ V4L2_STD_OBJECT_PROPS,
+ PROP_QUEUE_SIZE,
+ PROP_ALWAYS_COPY,
+ PROP_DECIMATE
+};
+
+GST_IMPLEMENT_V4L2_PROBE_METHODS (GstV4l2SrcClass, gst_v4l2src);
+GST_IMPLEMENT_V4L2_COLOR_BALANCE_METHODS (GstV4l2Src, gst_v4l2src);
+GST_IMPLEMENT_V4L2_TUNER_METHODS (GstV4l2Src, gst_v4l2src);
+#ifdef HAVE_XVIDEO
+GST_IMPLEMENT_V4L2_XOVERLAY_METHODS (GstV4l2Src, gst_v4l2src);
+#endif
+GST_IMPLEMENT_V4L2_VIDORIENT_METHODS (GstV4l2Src, gst_v4l2src);
+
+static void gst_v4l2src_uri_handler_init (gpointer g_iface,
+ gpointer iface_data);
+
+static gboolean
+gst_v4l2src_iface_supported (GstImplementsInterface * iface, GType iface_type)
+{
+ GstV4l2Object *v4l2object = GST_V4L2SRC (iface)->v4l2object;
+
+#ifdef HAVE_XVIDEO
+ if (!(iface_type == GST_TYPE_TUNER ||
+ iface_type == GST_TYPE_X_OVERLAY ||
+ iface_type == GST_TYPE_COLOR_BALANCE ||
+ iface_type == GST_TYPE_VIDEO_ORIENTATION))
+ return FALSE;
+#else
+ if (!(iface_type == GST_TYPE_TUNER ||
+ iface_type == GST_TYPE_COLOR_BALANCE ||
+ iface_type == GST_TYPE_VIDEO_ORIENTATION))
+ return FALSE;
+#endif
+
+ if (v4l2object->video_fd == -1)
+ return FALSE;
+
+#ifdef HAVE_XVIDEO
+ if (iface_type == GST_TYPE_X_OVERLAY && !GST_V4L2_IS_OVERLAY (v4l2object))
+ return FALSE;
+#endif
+
+ return TRUE;
+}
+
+static void
+gst_v4l2src_interface_init (GstImplementsInterfaceClass * klass)
+{
+ /*
+ * default virtual functions
+ */
+ klass->supported = gst_v4l2src_iface_supported;
+}
+
+static void
+gst_v4l2src_init_interfaces (GType type)
+{
+ static const GInterfaceInfo urihandler_info = {
+ gst_v4l2src_uri_handler_init,
+ NULL,
+ NULL
+ };
+
+ static const GInterfaceInfo v4l2iface_info = {
+ (GInterfaceInitFunc) gst_v4l2src_interface_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo v4l2_tuner_info = {
+ (GInterfaceInitFunc) gst_v4l2src_tuner_interface_init,
+ NULL,
+ NULL,
+ };
+#ifdef HAVE_XVIDEO
+ /* FIXME: does GstXOverlay for v4l2src make sense in a GStreamer context? */
+ static const GInterfaceInfo v4l2_xoverlay_info = {
+ (GInterfaceInitFunc) gst_v4l2src_xoverlay_interface_init,
+ NULL,
+ NULL,
+ };
+#endif
+ static const GInterfaceInfo v4l2_colorbalance_info = {
+ (GInterfaceInitFunc) gst_v4l2src_color_balance_interface_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo v4l2_videoorientation_info = {
+ (GInterfaceInitFunc) gst_v4l2src_video_orientation_interface_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo v4l2_propertyprobe_info = {
+ (GInterfaceInitFunc) gst_v4l2src_property_probe_interface_init,
+ NULL,
+ NULL,
+ };
+
+ g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info);
+ g_type_add_interface_static (type,
+ GST_TYPE_IMPLEMENTS_INTERFACE, &v4l2iface_info);
+ g_type_add_interface_static (type, GST_TYPE_TUNER, &v4l2_tuner_info);
+#ifdef HAVE_XVIDEO
+ g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &v4l2_xoverlay_info);
+#endif
+ g_type_add_interface_static (type,
+ GST_TYPE_COLOR_BALANCE, &v4l2_colorbalance_info);
+ g_type_add_interface_static (type,
+ GST_TYPE_VIDEO_ORIENTATION, &v4l2_videoorientation_info);
+ g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
+ &v4l2_propertyprobe_info);
+}
+
+GST_BOILERPLATE_FULL (GstV4l2Src, gst_v4l2src, GstPushSrc, GST_TYPE_PUSH_SRC,
+ gst_v4l2src_init_interfaces);
+
+static void gst_v4l2src_dispose (GObject * object);
+static void gst_v4l2src_finalize (GstV4l2Src * v4l2src);
+
+/* element methods */
+static GstStateChangeReturn gst_v4l2src_change_state (GstElement * element,
+ GstStateChange transition);
+
+/* basesrc methods */
+static gboolean gst_v4l2src_start (GstBaseSrc * src);
+static gboolean gst_v4l2src_unlock (GstBaseSrc * src);
+static gboolean gst_v4l2src_unlock_stop (GstBaseSrc * src);
+static gboolean gst_v4l2src_stop (GstBaseSrc * src);
+static gboolean gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps);
+static GstCaps *gst_v4l2src_get_caps (GstBaseSrc * src);
+static gboolean gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query);
+static GstFlowReturn gst_v4l2src_create (GstPushSrc * src, GstBuffer ** out);
+static void gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
+static gboolean gst_v4l2src_negotiate (GstBaseSrc * basesrc);
+
+static void gst_v4l2src_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_v4l2src_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+/* get_frame io methods */
+static GstFlowReturn
+gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf);
+static GstFlowReturn
+gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf);
+
+static void
+gst_v4l2src_base_init (gpointer g_class)
+{
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+ GstV4l2SrcClass *gstv4l2src_class = GST_V4L2SRC_CLASS (g_class);
+ GstPadTemplate *pad_template;
+
+ gstv4l2src_class->v4l2_class_devices = NULL;
+
+ GST_DEBUG_CATEGORY_INIT (v4l2src_debug, "v4l2src", 0, "V4L2 source element");
+
+ gst_element_class_set_details_simple (gstelement_class,
+ "Video (video4linux2) Source", "Source/Video",
+ "Reads frames from a Video4Linux2 device",
+ "Edgard Lima <edgard.lima@indt.org.br>,"
+ " Stefan Kost <ensonic@users.sf.net>");
+
+ pad_template =
+ gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+ gst_v4l2_object_get_all_caps ());
+ gst_element_class_add_pad_template (gstelement_class, pad_template);
+ gst_object_unref (pad_template);
+}
+
+static void
+gst_v4l2src_class_init (GstV4l2SrcClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *element_class;
+ GstBaseSrcClass *basesrc_class;
+ GstPushSrcClass *pushsrc_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ element_class = GST_ELEMENT_CLASS (klass);
+ basesrc_class = GST_BASE_SRC_CLASS (klass);
+ pushsrc_class = GST_PUSH_SRC_CLASS (klass);
+
+ gobject_class->dispose = gst_v4l2src_dispose;
+ gobject_class->finalize = (GObjectFinalizeFunc) gst_v4l2src_finalize;
+ gobject_class->set_property = gst_v4l2src_set_property;
+ gobject_class->get_property = gst_v4l2src_get_property;
+
+ element_class->change_state = gst_v4l2src_change_state;
+
+ gst_v4l2_object_install_properties_helper (gobject_class,
+ DEFAULT_PROP_DEVICE);
+ g_object_class_install_property (gobject_class, PROP_QUEUE_SIZE,
+ g_param_spec_uint ("queue-size", "Queue size",
+ "Number of buffers to be enqueud in the driver in streaming mode",
+ GST_V4L2_MIN_BUFFERS, GST_V4L2_MAX_BUFFERS, PROP_DEF_QUEUE_SIZE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_ALWAYS_COPY,
+ g_param_spec_boolean ("always-copy", "Always Copy",
+ "If the buffer will or not be used directly from mmap",
+ PROP_DEF_ALWAYS_COPY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstV4l2Src:decimate
+ *
+ * Only use every nth frame
+ *
+ * Since: 0.10.26
+ */
+ g_object_class_install_property (gobject_class, PROP_DECIMATE,
+ g_param_spec_int ("decimate", "Decimate",
+ "Only use every nth frame", 1, G_MAXINT,
+ PROP_DEF_DECIMATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_get_caps);
+ basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_set_caps);
+ basesrc_class->start = GST_DEBUG_FUNCPTR (gst_v4l2src_start);
+ basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_v4l2src_unlock);
+ basesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_v4l2src_unlock_stop);
+ basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_v4l2src_stop);
+ basesrc_class->query = GST_DEBUG_FUNCPTR (gst_v4l2src_query);
+ basesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_v4l2src_fixate);
+ basesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_v4l2src_negotiate);
+
+ pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_v4l2src_create);
+}
+
+static void
+gst_v4l2src_init (GstV4l2Src * v4l2src, GstV4l2SrcClass * klass)
+{
+ /* fixme: give an update_fps_function */
+ v4l2src->v4l2object = gst_v4l2_object_new (GST_ELEMENT (v4l2src),
+ V4L2_BUF_TYPE_VIDEO_CAPTURE, DEFAULT_PROP_DEVICE,
+ gst_v4l2_get_input, gst_v4l2_set_input, NULL);
+
+ /* number of buffers requested */
+ v4l2src->num_buffers = PROP_DEF_QUEUE_SIZE;
+
+ v4l2src->always_copy = PROP_DEF_ALWAYS_COPY;
+ v4l2src->decimate = PROP_DEF_DECIMATE;
+
+ v4l2src->is_capturing = FALSE;
+
+ gst_base_src_set_format (GST_BASE_SRC (v4l2src), GST_FORMAT_TIME);
+ gst_base_src_set_live (GST_BASE_SRC (v4l2src), TRUE);
+
+ v4l2src->fps_d = 0;
+ v4l2src->fps_n = 0;
+}
+
+
+static void
+gst_v4l2src_dispose (GObject * object)
+{
+ GstV4l2Src *v4l2src = GST_V4L2SRC (object);
+
+ if (v4l2src->probed_caps) {
+ gst_caps_unref (v4l2src->probed_caps);
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+
+static void
+gst_v4l2src_finalize (GstV4l2Src * v4l2src)
+{
+ gst_v4l2_object_destroy (v4l2src->v4l2object);
+
+ G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (v4l2src));
+}
+
+
+static void
+gst_v4l2src_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ GstV4l2Src *v4l2src = GST_V4L2SRC (object);
+
+ if (!gst_v4l2_object_set_property_helper (v4l2src->v4l2object,
+ prop_id, value, pspec)) {
+ switch (prop_id) {
+ case PROP_QUEUE_SIZE:
+ v4l2src->num_buffers = g_value_get_uint (value);
+ break;
+ case PROP_ALWAYS_COPY:
+ v4l2src->always_copy = g_value_get_boolean (value);
+ break;
+ case PROP_DECIMATE:
+ v4l2src->decimate = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ }
+}
+
+
+static void
+gst_v4l2src_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ GstV4l2Src *v4l2src = GST_V4L2SRC (object);
+
+ if (!gst_v4l2_object_get_property_helper (v4l2src->v4l2object,
+ prop_id, value, pspec)) {
+ switch (prop_id) {
+ case PROP_QUEUE_SIZE:
+ g_value_set_uint (value, v4l2src->num_buffers);
+ break;
+ case PROP_ALWAYS_COPY:
+ g_value_set_boolean (value, v4l2src->always_copy);
+ break;
+ case PROP_DECIMATE:
+ g_value_set_int (value, v4l2src->decimate);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ }
+}
+
+
+/* this function is a bit of a last resort */
+static void
+gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps)
+{
+ GstStructure *structure;
+ gint i;
+
+ GST_DEBUG_OBJECT (basesrc, "fixating caps %" GST_PTR_FORMAT, caps);
+
+ for (i = 0; i < gst_caps_get_size (caps); ++i) {
+ const GValue *v;
+
+ structure = gst_caps_get_structure (caps, i);
+
+ /* FIXME such sizes? we usually fixate to something in the 320x200
+ * range... */
+ /* We are fixating to greater possble size (limited to GST_V4L2_MAX_SIZE)
+ and the maximum framerate resolution for that size */
+ gst_structure_fixate_field_nearest_int (structure, "width",
+ GST_V4L2_MAX_SIZE);
+ gst_structure_fixate_field_nearest_int (structure, "height",
+ GST_V4L2_MAX_SIZE);
+ gst_structure_fixate_field_nearest_fraction (structure, "framerate",
+ G_MAXINT, 1);
+
+ v = gst_structure_get_value (structure, "format");
+ if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) {
+ guint32 fourcc;
+
+ g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST);
+
+ fourcc = gst_value_get_fourcc (gst_value_list_get_value (v, 0));
+ gst_structure_set (structure, "format", GST_TYPE_FOURCC, fourcc, NULL);
+ }
+ }
+
+ GST_DEBUG_OBJECT (basesrc, "fixated caps %" GST_PTR_FORMAT, caps);
+}
+
+
+static gboolean
+gst_v4l2src_negotiate (GstBaseSrc * basesrc)
+{
+ GstCaps *thiscaps;
+ GstCaps *caps = NULL;
+ GstCaps *peercaps = NULL;
+ gboolean result = FALSE;
+
+ /* first see what is possible on our source pad */
+ thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
+ GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
+ LOG_CAPS (basesrc, thiscaps);
+
+ /* nothing or anything is allowed, we're done */
+ if (thiscaps == NULL || gst_caps_is_any (thiscaps))
+ goto no_nego_needed;
+
+ /* get the peer caps */
+ peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
+ GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
+ LOG_CAPS (basesrc, peercaps);
+ if (peercaps && !gst_caps_is_any (peercaps)) {
+ GstCaps *icaps = NULL;
+ int i;
+
+ /* Prefer the first caps we are compatible with that the peer proposed */
+ for (i = 0; i < gst_caps_get_size (peercaps); i++) {
+ /* get intersection */
+ GstCaps *ipcaps = gst_caps_copy_nth (peercaps, i);
+
+ GST_DEBUG_OBJECT (basesrc, "peer: %" GST_PTR_FORMAT, ipcaps);
+ LOG_CAPS (basesrc, ipcaps);
+
+ icaps = gst_caps_intersect (thiscaps, ipcaps);
+ gst_caps_unref (ipcaps);
+
+ if (!gst_caps_is_empty (icaps))
+ break;
+
+ gst_caps_unref (icaps);
+ icaps = NULL;
+ }
+
+ GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, icaps);
+ LOG_CAPS (basesrc, icaps);
+ if (icaps) {
+ /* If there are multiple intersections pick the one with the smallest
+ * resolution strictly bigger then the first peer caps */
+ if (gst_caps_get_size (icaps) > 1) {
+ GstStructure *s = gst_caps_get_structure (peercaps, 0);
+
+ int best = 0;
+
+ int twidth, theight;
+
+ int width = G_MAXINT, height = G_MAXINT;
+
+ if (gst_structure_get_int (s, "width", &twidth)
+ && gst_structure_get_int (s, "height", &theight)) {
+
+ /* Walk the structure backwards to get the first entry of the
+ * smallest resolution bigger (or equal to) the preferred resolution)
+ */
+ for (i = gst_caps_get_size (icaps) - 1; i >= 0; i--) {
+ GstStructure *is = gst_caps_get_structure (icaps, i);
+
+ int w, h;
+
+ if (gst_structure_get_int (is, "width", &w)
+ && gst_structure_get_int (is, "height", &h)) {
+ if (w >= twidth && w <= width && h >= theight && h <= height) {
+ width = w;
+ height = h;
+ best = i;
+ }
+ }
+ }
+ }
+
+ caps = gst_caps_copy_nth (icaps, best);
+ gst_caps_unref (icaps);
+ } else {
+ caps = icaps;
+ }
+ }
+ gst_caps_unref (thiscaps);
+ } else {
+ /* no peer or peer have ANY caps, work with our own caps then */
+ caps = thiscaps;
+ }
+ if (peercaps)
+ gst_caps_unref (peercaps);
+ if (caps) {
+ caps = gst_caps_make_writable (caps);
+ gst_caps_truncate (caps);
+
+ /* now fixate */
+ if (!gst_caps_is_empty (caps)) {
+ gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
+ GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
+ LOG_CAPS (basesrc, caps);
+
+ if (gst_caps_is_any (caps)) {
+ /* hmm, still anything, so element can do anything and
+ * nego is not needed */
+ result = TRUE;
+ } else if (gst_caps_is_fixed (caps)) {
+ /* yay, fixed caps, use those then */
+ if (gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps))
+ result = TRUE;
+ }
+ }
+ gst_caps_unref (caps);
+ }
+ return result;
+
+no_nego_needed:
+ {
+ GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
+ if (thiscaps)
+ gst_caps_unref (thiscaps);
+ return TRUE;
+ }
+}
+
+static GstCaps *
+gst_v4l2src_get_caps (GstBaseSrc * src)
+{
+ GstV4l2Src *v4l2src = GST_V4L2SRC (src);
+ GstCaps *ret;
+ GSList *walk;
+ GSList *formats;
+
+ if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) {
+ /* FIXME: copy? */
+ return
+ gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
+ (v4l2src)));
+ }
+
+ if (v4l2src->probed_caps)
+ return gst_caps_ref (v4l2src->probed_caps);
+
+ formats = gst_v4l2_object_get_format_list (v4l2src->v4l2object);
+
+ ret = gst_caps_new_empty ();
+
+ for (walk = formats; walk; walk = walk->next) {
+ struct v4l2_fmtdesc *format;
+
+ GstStructure *template;
+
+ format = (struct v4l2_fmtdesc *) walk->data;
+
+ template = gst_v4l2_object_v4l2fourcc_to_structure (format->pixelformat);
+
+ if (template) {
+ GstCaps *tmp;
+
+ tmp =
+ gst_v4l2_object_probe_caps_for_format (v4l2src->v4l2object,
+ format->pixelformat, template);
+ if (tmp)
+ gst_caps_append (ret, tmp);
+
+ gst_structure_free (template);
+ } else {
+ GST_DEBUG_OBJECT (v4l2src, "unknown format %u", format->pixelformat);
+ }
+ }
+
+ v4l2src->probed_caps = gst_caps_ref (ret);
+
+ GST_INFO_OBJECT (v4l2src, "probed caps: %" GST_PTR_FORMAT, ret);
+
+ return ret;
+}
+
+static gboolean
+gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
+{
+ GstV4l2Src *v4l2src;
+ gint w = 0, h = 0;
+ gboolean interlaced;
+ struct v4l2_fmtdesc *format;
+ guint fps_n, fps_d;
+ guint size;
+
+ v4l2src = GST_V4L2SRC (src);
+
+ /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
+ if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object))
+ return FALSE;
+
+ /* make sure we stop capturing and dealloc buffers */
+ if (GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
+ /* both will throw an element-error on failure */
+ if (!gst_v4l2src_capture_stop (v4l2src))
+ return FALSE;
+ if (!gst_v4l2src_capture_deinit (v4l2src))
+ return FALSE;
+ }
+
+ /* we want our own v4l2 type of fourcc codes */
+ if (!gst_v4l2_object_get_caps_info (v4l2src->v4l2object, caps, &format, &w,
+ &h, &interlaced, &fps_n, &fps_d, &size)) {
+ GST_INFO_OBJECT (v4l2src,
+ "can't get capture format from caps %" GST_PTR_FORMAT, caps);
+ return FALSE;
+ }
+
+ GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d at %d/%d fps, "
+ "format %s", w, h, fps_n, fps_d, format->description);
+
+ if (!gst_v4l2src_set_capture (v4l2src, format->pixelformat, w, h,
+ interlaced, fps_n, fps_d))
+ /* error already posted */
+ return FALSE;
+
+ if (!gst_v4l2src_capture_init (v4l2src, caps))
+ return FALSE;
+
+ if (v4l2src->use_mmap) {
+ v4l2src->get_frame = gst_v4l2src_get_mmap;
+ } else {
+ v4l2src->get_frame = gst_v4l2src_get_read;
+ }
+
+ if (!gst_v4l2src_capture_start (v4l2src))
+ return FALSE;
+
+ /* now store the expected output size */
+ v4l2src->frame_byte_size = size;
+
+ return TRUE;
+}
+
+static gboolean
+gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query)
+{
+ GstV4l2Src *src;
+
+ gboolean res = FALSE;
+
+ src = GST_V4L2SRC (bsrc);
+
+ switch (GST_QUERY_TYPE (query)) {
+ case GST_QUERY_LATENCY:{
+ GstClockTime min_latency, max_latency;
+
+ /* device must be open */
+ if (!GST_V4L2_IS_OPEN (src->v4l2object)) {
+ GST_WARNING_OBJECT (src,
+ "Can't give latency since device isn't open !");
+ goto done;
+ }
+
+ /* we must have a framerate */
+ if (src->fps_n <= 0 || src->fps_d <= 0) {
+ GST_WARNING_OBJECT (src,
+ "Can't give latency since framerate isn't fixated !");
+ goto done;
+ }
+
+ /* min latency is the time to capture one frame */
+ min_latency =
+ gst_util_uint64_scale_int (GST_SECOND, src->fps_d, src->fps_n);
+
+ /* max latency is total duration of the frame buffer */
+ max_latency = src->num_buffers * min_latency;
+
+ GST_DEBUG_OBJECT (bsrc,
+ "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
+
+ /* we are always live, the min latency is 1 frame and the max latency is
+ * the complete buffer of frames. */
+ gst_query_set_latency (query, TRUE, min_latency, max_latency);
+
+ res = TRUE;
+ break;
+ }
+ default:
+ res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
+ break;
+ }
+
+done:
+
+ return res;
+}
+
+/* start and stop are not symmetric -- start will open the device, but not start
+ * capture. it's setcaps that will start capture, which is called via basesrc's
+ * negotiate method. stop will both stop capture and close the device.
+ */
+static gboolean
+gst_v4l2src_start (GstBaseSrc * src)
+{
+ GstV4l2Src *v4l2src = GST_V4L2SRC (src);
+
+ v4l2src->offset = 0;
+
+ /* activate settings for first frame */
+ v4l2src->ctrl_time = 0;
+ gst_object_sync_values (G_OBJECT (src), v4l2src->ctrl_time);
+
+ return TRUE;
+}
+
+static gboolean
+gst_v4l2src_unlock (GstBaseSrc * src)
+{
+ GstV4l2Src *v4l2src = GST_V4L2SRC (src);
+
+ GST_LOG_OBJECT (src, "Flushing");
+ gst_poll_set_flushing (v4l2src->v4l2object->poll, TRUE);
+
+ return TRUE;
+}
+
+static gboolean
+gst_v4l2src_unlock_stop (GstBaseSrc * src)
+{
+ GstV4l2Src *v4l2src = GST_V4L2SRC (src);
+
+ GST_LOG_OBJECT (src, "No longer flushing");
+ gst_poll_set_flushing (v4l2src->v4l2object->poll, FALSE);
+
+ return TRUE;
+}
+
+static gboolean
+gst_v4l2src_stop (GstBaseSrc * src)
+{
+ GstV4l2Src *v4l2src = GST_V4L2SRC (src);
+
+ if (GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)
+ && !gst_v4l2src_capture_stop (v4l2src))
+ return FALSE;
+
+ if (v4l2src->v4l2object->buffer != NULL) {
+ if (!gst_v4l2src_capture_deinit (v4l2src))
+ return FALSE;
+ }
+
+ v4l2src->fps_d = 0;
+ v4l2src->fps_n = 0;
+
+ return TRUE;
+}
+
+static GstStateChangeReturn
+gst_v4l2src_change_state (GstElement * element, GstStateChange transition)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ GstV4l2Src *v4l2src = GST_V4L2SRC (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ /* open the device */
+ if (!gst_v4l2_object_start (v4l2src->v4l2object))
+ return GST_STATE_CHANGE_FAILURE;
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ /* close the device */
+ if (!gst_v4l2_object_stop (v4l2src->v4l2object))
+ return GST_STATE_CHANGE_FAILURE;
+
+ if (v4l2src->probed_caps) {
+ gst_caps_unref (v4l2src->probed_caps);
+ v4l2src->probed_caps = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static GstFlowReturn
+gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
+{
+ gint amount;
+ gint ret;
+
+ gint buffersize;
+
+ buffersize = v4l2src->frame_byte_size;
+ /* In case the size per frame is unknown assume it's a streaming format (e.g.
+ * mpegts) and grab a reasonable default size instead */
+ if (buffersize == 0)
+ buffersize = GST_BASE_SRC (v4l2src)->blocksize;
+
+ *buf = gst_buffer_new_and_alloc (buffersize);
+
+ do {
+ ret = gst_poll_wait (v4l2src->v4l2object->poll, GST_CLOCK_TIME_NONE);
+ if (G_UNLIKELY (ret < 0)) {
+ if (errno == EBUSY)
+ goto stopped;
+ if (errno == ENXIO) {
+ GST_DEBUG_OBJECT (v4l2src,
+ "v4l2 device doesn't support polling. Disabling");
+ v4l2src->v4l2object->can_poll_device = FALSE;
+ } else {
+ if (errno != EAGAIN && errno != EINTR)
+ goto select_error;
+ }
+ }
+ amount =
+ v4l2_read (v4l2src->v4l2object->video_fd, GST_BUFFER_DATA (*buf),
+ buffersize);
+ if (amount == buffersize) {
+ break;
+ } else if (amount == -1) {
+ if (errno == EAGAIN || errno == EINTR) {
+ continue;
+ } else
+ goto read_error;
+ } else {
+ /* short reads can happen if a signal interrupts the read */
+ continue;
+ }
+ } while (TRUE);
+
+ /* we set the buffer metadata in gst_v4l2src_create() */
+
+ return GST_FLOW_OK;
+
+ /* ERRORS */
+select_error:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
+ ("select error %d: %s (%d)", ret, g_strerror (errno), errno));
+ return GST_FLOW_ERROR;
+ }
+stopped:
+ {
+ GST_DEBUG ("stop called");
+ return GST_FLOW_WRONG_STATE;
+ }
+read_error:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+ (_("Error reading %d bytes from device '%s'."),
+ buffersize, v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
+ gst_buffer_unref (*buf);
+ return GST_FLOW_ERROR;
+ }
+}
+
+static GstFlowReturn
+gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf)
+{
+ GstBuffer *temp;
+ GstFlowReturn ret;
+ guint size;
+ guint count = 0;
+
+again:
+ ret = gst_v4l2src_grab_frame (v4l2src, &temp);
+ if (G_UNLIKELY (ret != GST_FLOW_OK))
+ goto done;
+
+ if (v4l2src->frame_byte_size > 0) {
+ size = GST_BUFFER_SIZE (temp);
+
+ /* if size does not match what we expected, try again */
+ if (size != v4l2src->frame_byte_size) {
+ GST_ELEMENT_WARNING (v4l2src, RESOURCE, READ,
+ (_("Got unexpected frame size of %u instead of %u."),
+ size, v4l2src->frame_byte_size), (NULL));
+ gst_buffer_unref (temp);
+ if (count++ > 50)
+ goto size_error;
+
+ goto again;
+ }
+ }
+
+ *buf = temp;
+done:
+ return ret;
+
+ /* ERRORS */
+size_error:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+ (_("Error reading %d bytes on device '%s'."),
+ v4l2src->frame_byte_size, v4l2src->v4l2object->videodev), (NULL));
+ return GST_FLOW_ERROR;
+ }
+}
+
+static GstFlowReturn
+gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
+{
+ GstV4l2Src *v4l2src = GST_V4L2SRC (src);
+ int i;
+ GstFlowReturn ret;
+
+ for (i = 0; i < v4l2src->decimate - 1; i++) {
+ ret = v4l2src->get_frame (v4l2src, buf);
+ if (ret != GST_FLOW_OK) {
+ return ret;
+ }
+ gst_buffer_unref (*buf);
+ }
+
+ ret = v4l2src->get_frame (v4l2src, buf);
+
+ /* set buffer metadata */
+ if (G_LIKELY (ret == GST_FLOW_OK && *buf)) {
+ GstClock *clock;
+ GstClockTime timestamp;
+
+ GST_BUFFER_OFFSET (*buf) = v4l2src->offset++;
+ GST_BUFFER_OFFSET_END (*buf) = v4l2src->offset;
+
+ /* timestamps, LOCK to get clock and base time. */
+ /* FIXME: element clock and base_time is rarely changing */
+ GST_OBJECT_LOCK (v4l2src);
+ if ((clock = GST_ELEMENT_CLOCK (v4l2src))) {
+ /* we have a clock, get base time and ref clock */
+ timestamp = GST_ELEMENT (v4l2src)->base_time;
+ gst_object_ref (clock);
+ } else {
+ /* no clock, can't set timestamps */
+ timestamp = GST_CLOCK_TIME_NONE;
+ }
+ GST_OBJECT_UNLOCK (v4l2src);
+
+ if (G_LIKELY (clock)) {
+ /* the time now is the time of the clock minus the base time */
+ timestamp = gst_clock_get_time (clock) - timestamp;
+ gst_object_unref (clock);
+
+ /* if we have a framerate adjust timestamp for frame latency */
+ if (GST_CLOCK_TIME_IS_VALID (v4l2src->duration)) {
+ if (timestamp > v4l2src->duration)
+ timestamp -= v4l2src->duration;
+ else
+ timestamp = 0;
+ }
+ }
+
+ /* activate settings for next frame */
+ if (GST_CLOCK_TIME_IS_VALID (v4l2src->duration)) {
+ v4l2src->ctrl_time += v4l2src->duration;
+ } else {
+ /* this is not very good (as it should be the next timestamp),
+ * still good enough for linear fades (as long as it is not -1)
+ */
+ v4l2src->ctrl_time = timestamp;
+ }
+ gst_object_sync_values (G_OBJECT (src), v4l2src->ctrl_time);
+ GST_INFO_OBJECT (src, "sync to %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (v4l2src->ctrl_time));
+
+ /* FIXME: use the timestamp from the buffer itself! */
+ GST_BUFFER_TIMESTAMP (*buf) = timestamp;
+ GST_BUFFER_DURATION (*buf) = v4l2src->duration;
+ }
+ return ret;
+}
+
+
+/* GstURIHandler interface */
+static GstURIType
+gst_v4l2src_uri_get_type (void)
+{
+ return GST_URI_SRC;
+}
+
+static gchar **
+gst_v4l2src_uri_get_protocols (void)
+{
+ static gchar *protocols[] = { (char *) "v4l2", NULL };
+
+ return protocols;
+}
+
+static const gchar *
+gst_v4l2src_uri_get_uri (GstURIHandler * handler)
+{
+ GstV4l2Src *v4l2src = GST_V4L2SRC (handler);
+
+ if (v4l2src->v4l2object->videodev != NULL) {
+ gchar uri[256];
+
+ /* need to return a const string, but also don't want to leak the generated
+ * string, so just intern it - there's a limited number of video devices
+ * after all */
+ g_snprintf (uri, sizeof (uri), "v4l2://%s", v4l2src->v4l2object->videodev);
+ return g_intern_string (uri);
+ }
+
+ return "v4l2://";
+}
+
+static gboolean
+gst_v4l2src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
+{
+ GstV4l2Src *v4l2src = GST_V4L2SRC (handler);
+ const gchar *device = DEFAULT_PROP_DEVICE;
+
+ if (strcmp (uri, "v4l2://") != 0) {
+ device = uri + 7;
+ }
+ g_object_set (v4l2src, "device", device, NULL);
+
+ return TRUE;
+}
+
+
+static void
+gst_v4l2src_uri_handler_init (gpointer g_iface, gpointer iface_data)
+{
+ GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
+
+ iface->get_type = gst_v4l2src_uri_get_type;
+ iface->get_protocols = gst_v4l2src_uri_get_protocols;
+ iface->get_uri = gst_v4l2src_uri_get_uri;
+ iface->set_uri = gst_v4l2src_uri_set_uri;
+}
diff --git a/sys/v4l2/gstv4l2src.h b/sys/v4l2/gstv4l2src.h
new file mode 100644
index 0000000..0dd794a
--- /dev/null
+++ b/sys/v4l2/gstv4l2src.h
@@ -0,0 +1,102 @@
+/* GStreamer
+ *
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2src.h: BT8x8/V4L2 source element
+ *
+ * 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.
+ */
+
+#ifndef __GST_V4L2SRC_H__
+#define __GST_V4L2SRC_H__
+
+#include <gstv4l2object.h>
+#include <gstv4l2bufferpool.h>
+
+GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_V4L2SRC \
+ (gst_v4l2src_get_type())
+#define GST_V4L2SRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4L2SRC,GstV4l2Src))
+#define GST_V4L2SRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4L2SRC,GstV4l2SrcClass))
+#define GST_IS_V4L2SRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4L2SRC))
+#define GST_IS_V4L2SRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4L2SRC))
+
+typedef struct _GstV4l2Src GstV4l2Src;
+typedef struct _GstV4l2SrcClass GstV4l2SrcClass;
+
+typedef GstFlowReturn (*GstV4l2SrcGetFunc)(GstV4l2Src * v4l2src, GstBuffer ** buf);
+
+/**
+ * GstV4l2Src:
+ *
+ * Opaque object.
+ */
+struct _GstV4l2Src
+{
+ GstPushSrc pushsrc;
+
+ /*< private >*/
+ GstV4l2Object * v4l2object;
+
+ /* pads */
+ GstCaps *probed_caps;
+
+ /* buffer handling */
+ GstV4l2BufferPool *pool;
+
+ guint32 num_buffers;
+ gboolean use_mmap;
+ guint32 frame_byte_size;
+
+ /* if the buffer will be or not used from directly mmap */
+ gboolean always_copy;
+
+ int decimate;
+
+ /* True if we want to stop */
+ gboolean quit;
+ gboolean is_capturing;
+
+ guint64 offset;
+
+ gint fps_d, fps_n; /* framerate if device is open */
+ GstClockTime duration; /* duration of one frame */
+
+ GstClockTime ctrl_time;
+
+ GstV4l2SrcGetFunc get_frame;
+};
+
+struct _GstV4l2SrcClass
+{
+ GstPushSrcClass parent_class;
+
+ GList *v4l2_class_devices;
+};
+
+GType gst_v4l2src_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_V4L2SRC_H__ */
diff --git a/sys/v4l2/gstv4l2tuner.c b/sys/v4l2/gstv4l2tuner.c
new file mode 100644
index 0000000..a805396
--- /dev/null
+++ b/sys/v4l2/gstv4l2tuner.c
@@ -0,0 +1,364 @@
+/* GStreamer
+ *
+ * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2tuner.c: tuner interface implementation for V4L2
+ *
+ * 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 <gst/gst.h>
+
+#include "gstv4l2tuner.h"
+#include "gstv4l2object.h"
+#include "v4l2_calls.h"
+#include "v4l2src_calls.h"
+
+static void gst_v4l2_tuner_channel_class_init (GstV4l2TunerChannelClass *
+ klass);
+static void gst_v4l2_tuner_channel_init (GstV4l2TunerChannel * channel);
+
+static void gst_v4l2_tuner_norm_class_init (GstV4l2TunerNormClass * klass);
+static void gst_v4l2_tuner_norm_init (GstV4l2TunerNorm * norm);
+
+static GstTunerNormClass *norm_parent_class = NULL;
+static GstTunerChannelClass *channel_parent_class = NULL;
+
+GType
+gst_v4l2_tuner_channel_get_type (void)
+{
+ static GType gst_v4l2_tuner_channel_type = 0;
+
+ if (!gst_v4l2_tuner_channel_type) {
+ static const GTypeInfo v4l2_tuner_channel_info = {
+ sizeof (GstV4l2TunerChannelClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gst_v4l2_tuner_channel_class_init,
+ NULL,
+ NULL,
+ sizeof (GstV4l2TunerChannel),
+ 0,
+ (GInstanceInitFunc) gst_v4l2_tuner_channel_init,
+ NULL
+ };
+
+ gst_v4l2_tuner_channel_type =
+ g_type_register_static (GST_TYPE_TUNER_CHANNEL,
+ "GstV4l2TunerChannel", &v4l2_tuner_channel_info, 0);
+ }
+
+ return gst_v4l2_tuner_channel_type;
+}
+
+static void
+gst_v4l2_tuner_channel_class_init (GstV4l2TunerChannelClass * klass)
+{
+ channel_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+gst_v4l2_tuner_channel_init (GstV4l2TunerChannel * channel)
+{
+ channel->index = (guint32) - 1;
+ channel->tuner = (guint32) - 1;
+ channel->audio = (guint32) - 1;
+}
+
+GType
+gst_v4l2_tuner_norm_get_type (void)
+{
+ static GType gst_v4l2_tuner_norm_type = 0;
+
+ if (!gst_v4l2_tuner_norm_type) {
+ static const GTypeInfo v4l2_tuner_norm_info = {
+ sizeof (GstV4l2TunerNormClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gst_v4l2_tuner_norm_class_init,
+ NULL,
+ NULL,
+ sizeof (GstV4l2TunerNorm),
+ 0,
+ (GInstanceInitFunc) gst_v4l2_tuner_norm_init,
+ NULL
+ };
+
+ gst_v4l2_tuner_norm_type =
+ g_type_register_static (GST_TYPE_TUNER_NORM,
+ "GstV4l2TunerNorm", &v4l2_tuner_norm_info, 0);
+ }
+
+ return gst_v4l2_tuner_norm_type;
+}
+
+static void
+gst_v4l2_tuner_norm_class_init (GstV4l2TunerNormClass * klass)
+{
+ norm_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+gst_v4l2_tuner_norm_init (GstV4l2TunerNorm * norm)
+{
+ norm->index = 0;
+}
+
+static G_GNUC_UNUSED gboolean
+gst_v4l2_tuner_contains_channel (GstV4l2Object * v4l2object,
+ GstV4l2TunerChannel * v4l2channel)
+{
+ const GList *item;
+
+ for (item = v4l2object->channels; item != NULL; item = item->next)
+ if (item->data == v4l2channel)
+ return TRUE;
+
+ return FALSE;
+}
+
+const GList *
+gst_v4l2_tuner_list_channels (GstV4l2Object * v4l2object)
+{
+ return v4l2object->channels;
+}
+
+gboolean
+gst_v4l2_tuner_set_channel (GstV4l2Object * v4l2object,
+ GstTunerChannel * channel)
+{
+ GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel);
+
+ /* assert that we're opened and that we're using a known item */
+ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), FALSE);
+ g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2object,
+ v4l2channel), FALSE);
+
+ if (v4l2object->set_in_out_func (v4l2object, v4l2channel->index)) {
+ gst_tuner_channel_changed (GST_TUNER (v4l2object->element), channel);
+ /* can FPS change here? */
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+GstTunerChannel *
+gst_v4l2_tuner_get_channel (GstV4l2Object * v4l2object)
+{
+ GList *item;
+ gint channel;
+
+ /* assert that we're opened and that we're using a known item */
+ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), NULL);
+
+ if (v4l2object->get_in_out_func (v4l2object, &channel)) {
+
+ for (item = v4l2object->channels; item != NULL; item = item->next) {
+ if (channel == GST_V4L2_TUNER_CHANNEL (item->data)->index)
+ return (GstTunerChannel *) item->data;
+ }
+
+ }
+
+ return NULL;
+}
+
+static G_GNUC_UNUSED gboolean
+gst_v4l2_tuner_contains_norm (GstV4l2Object * v4l2object,
+ GstV4l2TunerNorm * v4l2norm)
+{
+ const GList *item;
+
+ for (item = v4l2object->norms; item != NULL; item = item->next)
+ if (item->data == v4l2norm)
+ return TRUE;
+
+ return FALSE;
+}
+
+const GList *
+gst_v4l2_tuner_list_norms (GstV4l2Object * v4l2object)
+{
+ return v4l2object->norms;
+}
+
+void
+gst_v4l2_tuner_set_norm_and_notify (GstV4l2Object * v4l2object,
+ GstTunerNorm * norm)
+{
+ if (gst_v4l2_tuner_set_norm (v4l2object, norm)) {
+#if 0
+ g_object_notify (G_OBJECT (v4l2object->element), "norm");
+#endif
+ }
+}
+
+gboolean
+gst_v4l2_tuner_set_norm (GstV4l2Object * v4l2object, GstTunerNorm * norm)
+{
+ GstV4l2TunerNorm *v4l2norm = GST_V4L2_TUNER_NORM (norm);
+
+ /* assert that we're opened and that we're using a known item */
+ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), FALSE);
+ g_return_val_if_fail (gst_v4l2_tuner_contains_norm (v4l2object, v4l2norm),
+ FALSE);
+
+ if (gst_v4l2_set_norm (v4l2object, v4l2norm->index)) {
+ gst_tuner_norm_changed (GST_TUNER (v4l2object->element), norm);
+ if (v4l2object->update_fps_func)
+ v4l2object->update_fps_func (v4l2object);
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+GstTunerNorm *
+gst_v4l2_tuner_get_norm (GstV4l2Object * v4l2object)
+{
+ v4l2_std_id norm;
+
+ /* assert that we're opened and that we're using a known item */
+ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), NULL);
+
+ gst_v4l2_get_norm (v4l2object, &norm);
+
+ return gst_v4l2_tuner_get_norm_by_std_id (v4l2object, norm);
+}
+
+GstTunerNorm *
+gst_v4l2_tuner_get_norm_by_std_id (GstV4l2Object * v4l2object, v4l2_std_id norm)
+{
+ GList *item;
+
+ for (item = v4l2object->norms; item != NULL; item = item->next) {
+ if (norm & GST_V4L2_TUNER_NORM (item->data)->index)
+ return (GstTunerNorm *) item->data;
+ }
+
+ return NULL;
+}
+
+v4l2_std_id
+gst_v4l2_tuner_get_std_id_by_norm (GstV4l2Object * v4l2object,
+ GstTunerNorm * norm)
+{
+ GList *item;
+
+ for (item = v4l2object->norms; item != NULL; item = item->next) {
+ if (norm == GST_TUNER_NORM (item->data))
+ return GST_V4L2_TUNER_NORM (item->data)->index;
+ }
+
+ return 0;
+}
+
+void
+gst_v4l2_tuner_set_frequency_and_notify (GstV4l2Object * v4l2object,
+ GstTunerChannel * channel, gulong frequency)
+{
+ if (gst_v4l2_tuner_set_frequency (v4l2object, channel, frequency)) {
+#if 0
+ g_object_notify (G_OBJECT (v4l2object->element), "frequency");
+#endif
+ }
+}
+
+gboolean
+gst_v4l2_tuner_set_frequency (GstV4l2Object * v4l2object,
+ GstTunerChannel * channel, gulong frequency)
+{
+ GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel);
+ gint chan;
+
+ /* assert that we're opened and that we're using a known item */
+ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), FALSE);
+ g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
+ GST_TUNER_CHANNEL_FREQUENCY), FALSE);
+ g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2object,
+ v4l2channel), FALSE);
+
+ if (v4l2object->get_in_out_func (v4l2object, &chan)) {
+ if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index &&
+ GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
+ if (gst_v4l2_set_frequency (v4l2object, v4l2channel->tuner, frequency)) {
+ gst_tuner_frequency_changed (GST_TUNER (v4l2object->element), channel,
+ frequency);
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+gulong
+gst_v4l2_tuner_get_frequency (GstV4l2Object * v4l2object,
+ GstTunerChannel * channel)
+{
+ GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel);
+ gint chan;
+ gulong frequency = 0;
+
+ /* assert that we're opened and that we're using a known item */
+ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), 0);
+ g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
+ GST_TUNER_CHANNEL_FREQUENCY), 0);
+ g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2object,
+ v4l2channel), 0);
+
+ if (v4l2object->get_in_out_func (v4l2object, &chan)) {
+ if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index &&
+ GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
+ gst_v4l2_get_frequency (v4l2object, v4l2channel->tuner, &frequency);
+ }
+ }
+
+ return frequency;
+}
+
+gint
+gst_v4l2_tuner_signal_strength (GstV4l2Object * v4l2object,
+ GstTunerChannel * channel)
+{
+ GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel);
+ gint chan;
+ gulong signal = 0;
+
+ /* assert that we're opened and that we're using a known item */
+ g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2object), 0);
+ g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
+ GST_TUNER_CHANNEL_FREQUENCY), 0);
+ g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2object,
+ v4l2channel), 0);
+
+ if (v4l2object->get_in_out_func (v4l2object, &chan)) {
+ if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index &&
+ GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
+ gst_v4l2_signal_strength (v4l2object, v4l2channel->tuner, &signal);
+ }
+ }
+
+ return signal;
+}
diff --git a/sys/v4l2/gstv4l2tuner.h b/sys/v4l2/gstv4l2tuner.h
new file mode 100644
index 0000000..699ca87
--- /dev/null
+++ b/sys/v4l2/gstv4l2tuner.h
@@ -0,0 +1,198 @@
+/* GStreamer
+ *
+ * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2tuner.h: tuner interface implementation for V4L2
+ *
+ * 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.
+ */
+
+#ifndef __GST_V4L2_TUNER_H__
+#define __GST_V4L2_TUNER_H__
+
+#include <gst/gst.h>
+#include <gst/interfaces/tuner.h>
+
+#include "gstv4l2object.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_V4L2_TUNER_CHANNEL \
+ (gst_v4l2_tuner_channel_get_type ())
+#define GST_V4L2_TUNER_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_TUNER_CHANNEL, \
+ GstV4l2TunerChannel))
+#define GST_V4L2_TUNER_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_TUNER_CHANNEL, \
+ GstV4l2TunerChannelClass))
+#define GST_IS_V4L2_TUNER_CHANNEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_TUNER_CHANNEL))
+#define GST_IS_V4L2_TUNER_CHANNEL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L2_TUNER_CHANNEL))
+
+typedef struct _GstV4l2TunerChannel {
+ GstTunerChannel parent;
+
+ guint32 index;
+ guint32 tuner;
+ guint32 audio;
+} GstV4l2TunerChannel;
+
+typedef struct _GstV4l2TunerChannelClass {
+ GstTunerChannelClass parent;
+} GstV4l2TunerChannelClass;
+
+#define GST_TYPE_V4L2_TUNER_NORM \
+ (gst_v4l2_tuner_norm_get_type ())
+#define GST_V4L2_TUNER_NORM(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_TUNER_NORM, \
+ GstV4l2TunerNorm))
+#define GST_V4L2_TUNER_NORM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_TUNER_NORM, \
+ GstV4l2TunerNormClass))
+#define GST_IS_V4L2_TUNER_NORM(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_TUNER_NORM))
+#define GST_IS_V4L2_TUNER_NORM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L2_TUNER_NORM))
+
+typedef struct _GstV4l2TunerNorm {
+ GstTunerNorm parent;
+
+ v4l2_std_id index;
+} GstV4l2TunerNorm;
+
+typedef struct _GstV4l2TunerNormClass {
+ GstTunerNormClass parent;
+} GstV4l2TunerNormClass;
+
+GType gst_v4l2_tuner_channel_get_type (void);
+GType gst_v4l2_tuner_norm_get_type (void);
+
+/* channels */
+const GList* gst_v4l2_tuner_list_channels (GstV4l2Object * v4l2object);
+GstTunerChannel* gst_v4l2_tuner_get_channel (GstV4l2Object * v4l2object);
+gboolean gst_v4l2_tuner_set_channel (GstV4l2Object * v4l2object,
+ GstTunerChannel * channel);
+/* norms */
+const GList* gst_v4l2_tuner_list_norms (GstV4l2Object * v4l2object);
+void gst_v4l2_tuner_set_norm_and_notify (GstV4l2Object * v4l2object,
+ GstTunerNorm * norm);
+GstTunerNorm* gst_v4l2_tuner_get_norm (GstV4l2Object * v4l2object);
+gboolean gst_v4l2_tuner_set_norm (GstV4l2Object * v4l2object,
+ GstTunerNorm * norm);
+GstTunerNorm* gst_v4l2_tuner_get_norm_by_std_id (GstV4l2Object * v4l2object,
+ v4l2_std_id norm);
+v4l2_std_id gst_v4l2_tuner_get_std_id_by_norm (GstV4l2Object * v4l2object,
+ GstTunerNorm * norm);
+
+/* frequency */
+void gst_v4l2_tuner_set_frequency_and_notify (GstV4l2Object * v4l2object,
+ GstTunerChannel * channel,
+ gulong frequency);
+gint gst_v4l2_tuner_signal_strength (GstV4l2Object * v4l2object,
+ GstTunerChannel * channel);
+gulong gst_v4l2_tuner_get_frequency (GstV4l2Object * v4l2object,
+ GstTunerChannel * channel);
+gboolean gst_v4l2_tuner_set_frequency (GstV4l2Object * v4l2object,
+ GstTunerChannel * channel,
+ gulong frequency);
+
+#define GST_IMPLEMENT_V4L2_TUNER_METHODS(Type, interface_as_function) \
+ \
+static const GList * \
+interface_as_function ## _tuner_list_channels (GstTuner * mixer) \
+{ \
+ Type *this = (Type*) mixer; \
+ return gst_v4l2_tuner_list_channels (this->v4l2object); \
+} \
+ \
+static void \
+interface_as_function ## _tuner_set_channel (GstTuner * mixer, \
+ GstTunerChannel * channel) \
+{ \
+ Type *this = (Type*) mixer; \
+ gst_v4l2_tuner_set_channel (this->v4l2object, channel); \
+} \
+static GstTunerChannel * \
+interface_as_function ## _tuner_get_channel (GstTuner * mixer) \
+{ \
+ Type *this = (Type*) mixer; \
+ return gst_v4l2_tuner_get_channel (this->v4l2object); \
+} \
+static const GList * \
+interface_as_function ## _tuner_list_norms (GstTuner * mixer) \
+{ \
+ Type *this = (Type*) mixer; \
+ return gst_v4l2_tuner_list_norms (this->v4l2object); \
+} \
+static void \
+interface_as_function ## _tuner_set_norm_and_notify (GstTuner * mixer, \
+ GstTunerNorm * norm) \
+{ \
+ Type *this = (Type*) mixer; \
+ gst_v4l2_tuner_set_norm_and_notify (this->v4l2object, norm); \
+} \
+static GstTunerNorm * \
+interface_as_function ## _tuner_get_norm (GstTuner * mixer) \
+{ \
+ Type *this = (Type*) mixer; \
+ return gst_v4l2_tuner_get_norm (this->v4l2object); \
+} \
+ \
+static void \
+interface_as_function ## _tuner_set_frequency_and_notify (GstTuner * mixer, \
+ GstTunerChannel * channel, \
+ gulong frequency) \
+{ \
+ Type *this = (Type*) mixer; \
+ gst_v4l2_tuner_set_frequency_and_notify (this->v4l2object, channel, frequency); \
+} \
+ \
+static gulong \
+interface_as_function ## _tuner_get_frequency (GstTuner * mixer, \
+ GstTunerChannel * channel) \
+{ \
+ Type *this = (Type*) mixer; \
+ return gst_v4l2_tuner_get_frequency (this->v4l2object, channel); \
+} \
+ \
+static gint \
+interface_as_function ## _tuner_signal_strength (GstTuner * mixer, \
+ GstTunerChannel * channel) \
+{ \
+ Type *this = (Type*) mixer; \
+ return gst_v4l2_tuner_signal_strength (this->v4l2object, channel); \
+} \
+ \
+static void \
+interface_as_function ## _tuner_interface_init (GstTunerClass * klass) \
+{ \
+ /* default virtual functions */ \
+ klass->list_channels = interface_as_function ## _tuner_list_channels; \
+ klass->set_channel = interface_as_function ## _tuner_set_channel; \
+ klass->get_channel = interface_as_function ## _tuner_get_channel; \
+ \
+ klass->list_norms = interface_as_function ## _tuner_list_norms; \
+ klass->set_norm = interface_as_function ## _tuner_set_norm_and_notify; \
+ klass->get_norm = interface_as_function ## _tuner_get_norm; \
+ \
+ klass->set_frequency = interface_as_function ## _tuner_set_frequency_and_notify; \
+ klass->get_frequency = interface_as_function ## _tuner_get_frequency; \
+ klass->signal_strength = interface_as_function ## _tuner_signal_strength; \
+} \
+
+#endif /* __GST_V4L2_TUNER_H__ */
diff --git a/sys/v4l2/gstv4l2vidorient.c b/sys/v4l2/gstv4l2vidorient.c
new file mode 100644
index 0000000..1fa47e7
--- /dev/null
+++ b/sys/v4l2/gstv4l2vidorient.c
@@ -0,0 +1,104 @@
+/* GStreamer
+ *
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2vidorient.c: video orientation interface implementation for V4L2
+ *
+ * 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 <gst/gst.h>
+
+#include "gstv4l2vidorient.h"
+#include "gstv4l2object.h"
+#include "v4l2_calls.h"
+#include "v4l2src_calls.h"
+
+GST_DEBUG_CATEGORY_STATIC (v4l2vo_debug);
+#define GST_CAT_DEFAULT v4l2vo_debug
+
+/* Those are deprecated calls that have been replaced */
+#ifndef V4L2_CID_HCENTER
+#define V4L2_CID_HCENTER V4L2_CID_PAN_RESET
+#endif
+#ifndef V4L2_CID_VCENTER
+#define V4L2_CID_VCENTER V4L2_CID_TILT_RESET
+#endif
+
+void
+gst_v4l2_video_orientation_interface_init (GstVideoOrientationInterface * klass)
+{
+ GST_DEBUG_CATEGORY_INIT (v4l2vo_debug, "v4l2vo", 0,
+ "V4L2 VideoOrientation interface debugging");
+}
+
+
+gboolean
+gst_v4l2_video_orientation_get_hflip (GstV4l2Object * v4l2object,
+ gboolean * flip)
+{
+
+ return gst_v4l2_get_attribute (v4l2object, V4L2_CID_HFLIP, flip);
+}
+
+gboolean
+gst_v4l2_video_orientation_get_vflip (GstV4l2Object * v4l2object,
+ gboolean * flip)
+{
+ return gst_v4l2_get_attribute (v4l2object, V4L2_CID_VFLIP, flip);
+}
+
+gboolean
+gst_v4l2_video_orientation_get_hcenter (GstV4l2Object * v4l2object,
+ gint * center)
+{
+ return gst_v4l2_get_attribute (v4l2object, V4L2_CID_HCENTER, center);
+}
+
+gboolean
+gst_v4l2_video_orientation_get_vcenter (GstV4l2Object * v4l2object,
+ gint * center)
+{
+ return gst_v4l2_get_attribute (v4l2object, V4L2_CID_VCENTER, center);
+}
+
+gboolean
+gst_v4l2_video_orientation_set_hflip (GstV4l2Object * v4l2object, gboolean flip)
+{
+ return gst_v4l2_set_attribute (v4l2object, V4L2_CID_HFLIP, flip);
+}
+
+gboolean
+gst_v4l2_video_orientation_set_vflip (GstV4l2Object * v4l2object, gboolean flip)
+{
+ return gst_v4l2_set_attribute (v4l2object, V4L2_CID_VFLIP, flip);
+}
+
+gboolean
+gst_v4l2_video_orientation_set_hcenter (GstV4l2Object * v4l2object, gint center)
+{
+ return gst_v4l2_set_attribute (v4l2object, V4L2_CID_HCENTER, center);
+}
+
+gboolean
+gst_v4l2_video_orientation_set_vcenter (GstV4l2Object * v4l2object, gint center)
+{
+ return gst_v4l2_set_attribute (v4l2object, V4L2_CID_VCENTER, center);
+}
diff --git a/sys/v4l2/gstv4l2vidorient.h b/sys/v4l2/gstv4l2vidorient.h
new file mode 100644
index 0000000..39682e2
--- /dev/null
+++ b/sys/v4l2/gstv4l2vidorient.h
@@ -0,0 +1,117 @@
+/* GStreamer
+ *
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2vidorient.h: video orientation interface implementation for V4L2
+ *
+ * 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.
+ */
+
+#ifndef __GST_V4L2_VIDORIENT_H__
+#define __GST_V4L2_VIDORIENT_H__
+
+#include <gst/gst.h>
+#include <gst/interfaces/videoorientation.h>
+
+#include "gstv4l2object.h"
+
+G_BEGIN_DECLS
+
+void gst_v4l2_video_orientation_interface_init (GstVideoOrientationInterface * klass);
+
+gboolean gst_v4l2_video_orientation_get_hflip (GstV4l2Object *v4l2object, gboolean *flip);
+gboolean gst_v4l2_video_orientation_get_vflip (GstV4l2Object *v4l2object, gboolean *flip);
+gboolean gst_v4l2_video_orientation_get_hcenter (GstV4l2Object *v4l2object, gint *center);
+gboolean gst_v4l2_video_orientation_get_vcenter (GstV4l2Object *v4l2object, gint *center);
+
+gboolean gst_v4l2_video_orientation_set_hflip (GstV4l2Object *v4l2object, gboolean flip);
+gboolean gst_v4l2_video_orientation_set_vflip (GstV4l2Object *v4l2object, gboolean flip);
+gboolean gst_v4l2_video_orientation_set_hcenter (GstV4l2Object *v4l2object, gint center);
+gboolean gst_v4l2_video_orientation_set_vcenter (GstV4l2Object *v4l2object, gint center);
+
+#define GST_IMPLEMENT_V4L2_VIDORIENT_METHODS(Type, interface_as_function) \
+ \
+ static gboolean \
+ interface_as_function ## _video_orientation_get_hflip (GstVideoOrientation *vo, gboolean *flip) \
+ { \
+ Type *this = (Type*) vo; \
+ return gst_v4l2_video_orientation_get_hflip (this->v4l2object, flip); \
+ } \
+ \
+ static gboolean \
+ interface_as_function ## _video_orientation_get_vflip (GstVideoOrientation *vo, gboolean *flip) \
+ { \
+ Type *this = (Type*) vo; \
+ return gst_v4l2_video_orientation_get_vflip (this->v4l2object, flip); \
+ } \
+ \
+ static gboolean \
+ interface_as_function ## _video_orientation_get_hcenter (GstVideoOrientation *vo, gint *center) \
+ { \
+ Type *this = (Type*) vo; \
+ return gst_v4l2_video_orientation_get_hcenter (this->v4l2object, center); \
+ } \
+ \
+ static gboolean \
+ interface_as_function ## _video_orientation_get_vcenter (GstVideoOrientation *vo, gint *center) \
+ { \
+ Type *this = (Type*) vo; \
+ return gst_v4l2_video_orientation_get_vcenter (this->v4l2object, center); \
+ } \
+ \
+ static gboolean \
+ interface_as_function ## _video_orientation_set_hflip (GstVideoOrientation *vo, gboolean flip) \
+ { \
+ Type *this = (Type*) vo; \
+ return gst_v4l2_video_orientation_set_hflip (this->v4l2object, flip); \
+ } \
+ \
+ static gboolean \
+ interface_as_function ## _video_orientation_set_vflip (GstVideoOrientation *vo, gboolean flip) \
+ { \
+ Type *this = (Type*) vo; \
+ return gst_v4l2_video_orientation_set_vflip (this->v4l2object, flip); \
+ } \
+ \
+ static gboolean \
+ interface_as_function ## _video_orientation_set_hcenter (GstVideoOrientation *vo, gint center) \
+ { \
+ Type *this = (Type*) vo; \
+ return gst_v4l2_video_orientation_set_hcenter (this->v4l2object, center); \
+ } \
+ \
+ static gboolean \
+ interface_as_function ## _video_orientation_set_vcenter (GstVideoOrientation *vo, gint center) \
+ { \
+ Type *this = (Type*) vo; \
+ return gst_v4l2_video_orientation_set_vcenter (this->v4l2object, center); \
+ } \
+ \
+ static void \
+ interface_as_function ## _video_orientation_interface_init (GstVideoOrientationInterface * klass) \
+ { \
+ /* default virtual functions */ \
+ klass->get_hflip = interface_as_function ## _video_orientation_get_hflip; \
+ klass->get_vflip = interface_as_function ## _video_orientation_get_vflip; \
+ klass->get_hcenter = interface_as_function ## _video_orientation_get_hcenter; \
+ klass->get_vcenter = interface_as_function ## _video_orientation_get_vcenter; \
+ klass->set_hflip = interface_as_function ## _video_orientation_set_hflip; \
+ klass->set_vflip = interface_as_function ## _video_orientation_set_vflip; \
+ klass->set_hcenter = interface_as_function ## _video_orientation_set_hcenter; \
+ klass->set_vcenter = interface_as_function ## _video_orientation_set_vcenter; \
+ }
+
+#endif /* __GST_V4L2_VIDORIENT_H__ */
diff --git a/sys/v4l2/gstv4l2xoverlay.c b/sys/v4l2/gstv4l2xoverlay.c
new file mode 100644
index 0000000..60d0919
--- /dev/null
+++ b/sys/v4l2/gstv4l2xoverlay.c
@@ -0,0 +1,486 @@
+/* GStreamer
+ *
+ * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2xoverlay.c: X-based overlay interface implementation for V4L2
+ *
+ * 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 <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+#include <sys/stat.h>
+
+#include <gst/interfaces/navigation.h>
+
+#include "gstv4l2xoverlay.h"
+#include "gstv4l2object.h"
+#include "v4l2_calls.h"
+
+#include "gst/gst-i18n-plugin.h"
+#include <gst/glib-compat-private.h>
+
+struct _GstV4l2Xv
+{
+ Display *dpy;
+ gint port, idle_id, event_id;
+ GMutex *mutex; /* to serialize calls to X11 */
+};
+
+GST_DEBUG_CATEGORY_STATIC (v4l2xv_debug);
+#define GST_CAT_DEFAULT v4l2xv_debug
+
+void
+gst_v4l2_xoverlay_interface_init (GstXOverlayClass * klass)
+{
+ GST_DEBUG_CATEGORY_INIT (v4l2xv_debug, "v4l2xv", 0,
+ "V4L2 XOverlay interface debugging");
+}
+
+static void
+gst_v4l2_xoverlay_open (GstV4l2Object * v4l2object)
+{
+ struct stat s;
+ GstV4l2Xv *v4l2xv;
+ const gchar *name = g_getenv ("DISPLAY");
+ unsigned int ver, rel, req, ev, err, anum;
+ int i, id = 0, first_id = 0, min;
+ XvAdaptorInfo *ai;
+ Display *dpy;
+
+ /* we need a display, obviously */
+ if (!name || !(dpy = XOpenDisplay (name))) {
+ GST_WARNING_OBJECT (v4l2object->element,
+ "No $DISPLAY set or failed to open - no overlay");
+ return;
+ }
+
+ /* First let's check that XVideo extension is available */
+ if (!XQueryExtension (dpy, "XVideo", &i, &i, &i)) {
+ GST_WARNING_OBJECT (v4l2object->element,
+ "Xv extension not available - no overlay");
+ XCloseDisplay (dpy);
+ return;
+ }
+
+ /* find port that belongs to this device */
+ if (XvQueryExtension (dpy, &ver, &rel, &req, &ev, &err) != Success) {
+ GST_WARNING_OBJECT (v4l2object->element,
+ "Xv extension not supported - no overlay");
+ XCloseDisplay (dpy);
+ return;
+ }
+ if (XvQueryAdaptors (dpy, DefaultRootWindow (dpy), &anum, &ai) != Success) {
+ GST_WARNING_OBJECT (v4l2object->element, "Failed to query Xv adaptors");
+ XCloseDisplay (dpy);
+ return;
+ }
+ if (fstat (v4l2object->video_fd, &s) < 0) {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
+ (_("Cannot identify device '%s'."), v4l2object->videodev),
+ GST_ERROR_SYSTEM);
+ XCloseDisplay (dpy);
+ return;
+ }
+ min = s.st_rdev & 0xff;
+ for (i = 0; i < anum; i++) {
+ GST_DEBUG_OBJECT (v4l2object->element, "found adapter: %s", ai[i].name);
+ if (!strcmp (ai[i].name, "video4linux2") ||
+ !strcmp (ai[i].name, "video4linux")) {
+ if (first_id == 0)
+ first_id = ai[i].base_id;
+
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "first_id=%d, base_id=%lu, min=%d", first_id, ai[i].base_id, min);
+
+ /* hmm... */
+ if (first_id != 0 && ai[i].base_id == first_id + min)
+ id = ai[i].base_id;
+ }
+ }
+ XvFreeAdaptorInfo (ai);
+
+ if (id == 0) {
+ GST_WARNING_OBJECT (v4l2object->element,
+ "Did not find XvPortID for device - no overlay");
+ XCloseDisplay (dpy);
+ return;
+ }
+
+ v4l2xv = g_new0 (GstV4l2Xv, 1);
+ v4l2xv->dpy = dpy;
+ v4l2xv->port = id;
+ v4l2xv->mutex = g_mutex_new ();
+ v4l2xv->idle_id = 0;
+ v4l2xv->event_id = 0;
+ v4l2object->xv = v4l2xv;
+
+ if (v4l2object->xwindow_id) {
+ gst_v4l2_xoverlay_set_window_handle (v4l2object, v4l2object->xwindow_id);
+ }
+}
+
+static void
+gst_v4l2_xoverlay_close (GstV4l2Object * v4l2object)
+{
+ GstV4l2Xv *v4l2xv = v4l2object->xv;
+
+ if (!v4l2object->xv)
+ return;
+
+ if (v4l2object->xwindow_id) {
+ gst_v4l2_xoverlay_set_window_handle (v4l2object, 0);
+ }
+
+ XCloseDisplay (v4l2xv->dpy);
+ g_mutex_free (v4l2xv->mutex);
+ if (v4l2xv->idle_id)
+ g_source_remove (v4l2xv->idle_id);
+ if (v4l2xv->event_id)
+ g_source_remove (v4l2xv->event_id);
+ g_free (v4l2xv);
+ v4l2object->xv = NULL;
+}
+
+void
+gst_v4l2_xoverlay_start (GstV4l2Object * v4l2object)
+{
+ if (v4l2object->xwindow_id) {
+ gst_v4l2_xoverlay_open (v4l2object);
+ }
+}
+
+void
+gst_v4l2_xoverlay_stop (GstV4l2Object * v4l2object)
+{
+ gst_v4l2_xoverlay_close (v4l2object);
+}
+
+/* should be called with mutex held */
+static gboolean
+get_render_rect (GstV4l2Object * v4l2object, GstVideoRectangle * rect)
+{
+ GstV4l2Xv *v4l2xv = v4l2object->xv;
+ if (v4l2xv && v4l2xv->dpy && v4l2object->xwindow_id) {
+ XWindowAttributes attr;
+ XGetWindowAttributes (v4l2xv->dpy, v4l2object->xwindow_id, &attr);
+ /* this is where we'd add support to maintain aspect ratio */
+ rect->x = 0;
+ rect->y = 0;
+ rect->w = attr.width;
+ rect->h = attr.height;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+gboolean
+gst_v4l2_xoverlay_get_render_rect (GstV4l2Object * v4l2object,
+ GstVideoRectangle * rect)
+{
+ GstV4l2Xv *v4l2xv = v4l2object->xv;
+ gboolean ret = FALSE;
+ if (v4l2xv) {
+ g_mutex_lock (v4l2xv->mutex);
+ ret = get_render_rect (v4l2object, rect);
+ g_mutex_unlock (v4l2xv->mutex);
+ }
+ return ret;
+}
+
+static void
+update_geometry (GstV4l2Object * v4l2object)
+{
+ GstV4l2Xv *v4l2xv = v4l2object->xv;
+ GstVideoRectangle rect;
+ if (!get_render_rect (v4l2object, &rect))
+ return;
+ /* note: we don't pass in valid video x/y/w/h.. currently the xserver
+ * doesn't need to know these, as they come from v4l2 by setting the
+ * crop..
+ */
+ XvPutVideo (v4l2xv->dpy, v4l2xv->port, v4l2object->xwindow_id,
+ DefaultGC (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy)),
+ 0, 0, rect.w, rect.h, rect.x, rect.y, rect.w, rect.h);
+}
+
+static gboolean
+idle_refresh (gpointer data)
+{
+ GstV4l2Object *v4l2object = GST_V4L2_OBJECT (data);
+ GstV4l2Xv *v4l2xv = v4l2object->xv;
+
+ GST_LOG_OBJECT (v4l2object->element, "idle refresh");
+
+ if (v4l2xv) {
+ g_mutex_lock (v4l2xv->mutex);
+
+ update_geometry (v4l2object);
+
+ v4l2xv->idle_id = 0;
+ g_mutex_unlock (v4l2xv->mutex);
+ }
+
+ /* once */
+ return FALSE;
+}
+
+
+static gboolean
+event_refresh (gpointer data)
+{
+ GstV4l2Object *v4l2object = GST_V4L2_OBJECT (data);
+ GstV4l2Xv *v4l2xv = v4l2object->xv;
+
+ GST_LOG_OBJECT (v4l2object->element, "event refresh");
+
+ if (v4l2xv) {
+ XEvent e;
+
+ g_mutex_lock (v4l2xv->mutex);
+
+ /* If the element supports navigation, collect the relavent input
+ * events and push them upstream as navigation events
+ */
+ if (GST_IS_NAVIGATION (v4l2object->element)) {
+ guint pointer_x = 0, pointer_y = 0;
+ gboolean pointer_moved = FALSE;
+
+ /* We get all pointer motion events, only the last position is
+ * interesting.
+ */
+ while (XCheckWindowEvent (v4l2xv->dpy, v4l2object->xwindow_id,
+ PointerMotionMask, &e)) {
+ switch (e.type) {
+ case MotionNotify:
+ pointer_x = e.xmotion.x;
+ pointer_y = e.xmotion.y;
+ pointer_moved = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ if (pointer_moved) {
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "pointer moved over window at %d,%d", pointer_x, pointer_y);
+ g_mutex_unlock (v4l2xv->mutex);
+ gst_navigation_send_mouse_event (GST_NAVIGATION (v4l2object->element),
+ "mouse-move", 0, e.xbutton.x, e.xbutton.y);
+ g_mutex_lock (v4l2xv->mutex);
+ }
+
+ /* We get all events on our window to throw them upstream
+ */
+ while (XCheckWindowEvent (v4l2xv->dpy, v4l2object->xwindow_id,
+ KeyPressMask | KeyReleaseMask |
+ ButtonPressMask | ButtonReleaseMask, &e)) {
+ KeySym keysym;
+ const char *key_str = NULL;
+
+ g_mutex_unlock (v4l2xv->mutex);
+
+ switch (e.type) {
+ case ButtonPress:
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "button %d pressed over window at %d,%d",
+ e.xbutton.button, e.xbutton.x, e.xbutton.y);
+ gst_navigation_send_mouse_event (GST_NAVIGATION
+ (v4l2object->element), "mouse-button-press", e.xbutton.button,
+ e.xbutton.x, e.xbutton.y);
+ break;
+ case ButtonRelease:
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "button %d released over window at %d,%d",
+ e.xbutton.button, e.xbutton.x, e.xbutton.y);
+ gst_navigation_send_mouse_event (GST_NAVIGATION
+ (v4l2object->element), "mouse-button-release", e.xbutton.button,
+ e.xbutton.x, e.xbutton.y);
+ break;
+ case KeyPress:
+ case KeyRelease:
+ g_mutex_lock (v4l2xv->mutex);
+ keysym = XKeycodeToKeysym (v4l2xv->dpy, e.xkey.keycode, 0);
+ if (keysym != NoSymbol) {
+ key_str = XKeysymToString (keysym);
+ } else {
+ key_str = "unknown";
+ }
+ g_mutex_unlock (v4l2xv->mutex);
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "key %d pressed over window at %d,%d (%s)",
+ e.xkey.keycode, e.xkey.x, e.xkey.y, key_str);
+ gst_navigation_send_key_event (GST_NAVIGATION (v4l2object->element),
+ e.type == KeyPress ? "key-press" : "key-release", key_str);
+ break;
+ default:
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "unhandled X event (%d)", e.type);
+ }
+
+ g_mutex_lock (v4l2xv->mutex);
+ }
+ }
+
+ /* Handle ConfigureNotify */
+ while (XCheckWindowEvent (v4l2xv->dpy, v4l2object->xwindow_id,
+ StructureNotifyMask, &e)) {
+ switch (e.type) {
+ case ConfigureNotify:
+ update_geometry (v4l2object);
+ break;
+ default:
+ break;
+ }
+ }
+ g_mutex_unlock (v4l2xv->mutex);
+ }
+
+ /* repeat */
+ return TRUE;
+}
+
+void
+gst_v4l2_xoverlay_set_window_handle (GstV4l2Object * v4l2object, guintptr id)
+{
+ GstV4l2Xv *v4l2xv;
+ XID xwindow_id = id;
+ gboolean change = (v4l2object->xwindow_id != xwindow_id);
+
+ GST_LOG_OBJECT (v4l2object->element, "Setting XID to %lx",
+ (gulong) xwindow_id);
+
+ if (!v4l2object->xv && GST_V4L2_IS_OPEN (v4l2object))
+ gst_v4l2_xoverlay_open (v4l2object);
+
+ v4l2xv = v4l2object->xv;
+
+ if (v4l2xv)
+ g_mutex_lock (v4l2xv->mutex);
+
+ if (change) {
+ if (v4l2object->xwindow_id && v4l2xv) {
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "Deactivating old port %lx", v4l2object->xwindow_id);
+
+ XvSelectPortNotify (v4l2xv->dpy, v4l2xv->port, 0);
+ XvSelectVideoNotify (v4l2xv->dpy, v4l2object->xwindow_id, 0);
+ XvStopVideo (v4l2xv->dpy, v4l2xv->port, v4l2object->xwindow_id);
+ }
+
+ v4l2object->xwindow_id = xwindow_id;
+ }
+
+ if (!v4l2xv || xwindow_id == 0) {
+ if (v4l2xv)
+ g_mutex_unlock (v4l2xv->mutex);
+ return;
+ }
+
+ if (change) {
+ GST_DEBUG_OBJECT (v4l2object->element, "Activating new port %lx",
+ xwindow_id);
+
+ /* draw */
+ XvSelectPortNotify (v4l2xv->dpy, v4l2xv->port, 1);
+ XvSelectVideoNotify (v4l2xv->dpy, v4l2object->xwindow_id, 1);
+ }
+
+ update_geometry (v4l2object);
+
+ if (v4l2xv->idle_id)
+ g_source_remove (v4l2xv->idle_id);
+ v4l2xv->idle_id = g_idle_add (idle_refresh, v4l2object);
+ g_mutex_unlock (v4l2xv->mutex);
+}
+
+/**
+ * gst_v4l2_xoverlay_prepare_xwindow_id:
+ * @v4l2object: the v4l2object
+ * @required: %TRUE if display is required (ie. TRUE for v4l2sink, but
+ * FALSE for any other element with optional overlay capabilities)
+ *
+ * Helper function to create a windo if none is set from the application.
+ */
+void
+gst_v4l2_xoverlay_prepare_xwindow_id (GstV4l2Object * v4l2object,
+ gboolean required)
+{
+ if (!GST_V4L2_IS_OVERLAY (v4l2object))
+ return;
+
+ gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (v4l2object->element));
+
+ if (required && !v4l2object->xwindow_id) {
+ GstV4l2Xv *v4l2xv;
+ Window win;
+ int width, height;
+ long event_mask;
+
+ if (!v4l2object->xv && GST_V4L2_IS_OPEN (v4l2object))
+ gst_v4l2_xoverlay_open (v4l2object);
+
+ v4l2xv = v4l2object->xv;
+
+ /* if xoverlay is not supported, just bail */
+ if (!v4l2xv)
+ return;
+
+ /* xoverlay is supported, but we don't have a window.. so create one */
+ GST_DEBUG_OBJECT (v4l2object->element, "creating window");
+
+ g_mutex_lock (v4l2xv->mutex);
+
+ width = XDisplayWidth (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy));
+ height = XDisplayHeight (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy));
+ GST_DEBUG_OBJECT (v4l2object->element, "dpy=%p", v4l2xv->dpy);
+
+ win = XCreateSimpleWindow (v4l2xv->dpy,
+ DefaultRootWindow (v4l2xv->dpy),
+ 0, 0, width, height, 0, 0,
+ XBlackPixel (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy)));
+
+ GST_DEBUG_OBJECT (v4l2object->element, "win=%lu", win);
+
+ event_mask = ExposureMask | StructureNotifyMask;
+ if (GST_IS_NAVIGATION (v4l2object->element)) {
+ event_mask |= PointerMotionMask |
+ KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask;
+ }
+ XSelectInput (v4l2xv->dpy, win, event_mask);
+ v4l2xv->event_id = g_timeout_add (45, event_refresh, v4l2object);
+
+ XMapRaised (v4l2xv->dpy, win);
+
+ XSync (v4l2xv->dpy, FALSE);
+
+ g_mutex_unlock (v4l2xv->mutex);
+
+ GST_DEBUG_OBJECT (v4l2object->element, "got window");
+
+ gst_v4l2_xoverlay_set_window_handle (v4l2object, win);
+ }
+}
diff --git a/sys/v4l2/gstv4l2xoverlay.h b/sys/v4l2/gstv4l2xoverlay.h
new file mode 100644
index 0000000..1a09306
--- /dev/null
+++ b/sys/v4l2/gstv4l2xoverlay.h
@@ -0,0 +1,70 @@
+/* GStreamer
+ *
+ * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * gstv4l2xoverlay.h: tv mixer interface implementation for V4L2
+ *
+ * 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.
+ */
+
+#ifndef __GST_V4L2_X_OVERLAY_H__
+#define __GST_V4L2_X_OVERLAY_H__
+
+#include <X11/X.h>
+
+#include <gst/gst.h>
+#include <gst/interfaces/xoverlay.h>
+#include <gst/interfaces/navigation.h>
+#include <gst/video/gstvideosink.h> /* for GstVideoRectange */
+
+#include "gstv4l2object.h"
+
+G_BEGIN_DECLS
+
+void gst_v4l2_xoverlay_start (GstV4l2Object *v4l2object);
+void gst_v4l2_xoverlay_stop (GstV4l2Object *v4l2object);
+gboolean gst_v4l2_xoverlay_get_render_rect (GstV4l2Object *v4l2object,
+ GstVideoRectangle *rect);
+
+void gst_v4l2_xoverlay_interface_init (GstXOverlayClass * klass);
+void gst_v4l2_xoverlay_set_window_handle (GstV4l2Object * v4l2object,
+ guintptr id);
+void gst_v4l2_xoverlay_prepare_xwindow_id (GstV4l2Object * v4l2object,
+ gboolean required);
+
+
+#define GST_IMPLEMENT_V4L2_XOVERLAY_METHODS(Type, interface_as_function) \
+ \
+static void \
+interface_as_function ## _xoverlay_set_window_handle (GstXOverlay * xoverlay, \
+ guintptr id) \
+{ \
+ Type *this = (Type*) xoverlay; \
+ gst_v4l2_xoverlay_set_window_handle (this->v4l2object, id); \
+} \
+ \
+static void \
+interface_as_function ## _xoverlay_interface_init (GstXOverlayClass * klass) \
+{ \
+ /* default virtual functions */ \
+ klass->set_window_handle = interface_as_function ## _xoverlay_set_window_handle; \
+ \
+ gst_v4l2_xoverlay_interface_init(klass); \
+} \
+
+
+#endif /* __GST_V4L2_X_OVERLAY_H__ */
diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c
new file mode 100644
index 0000000..309bfb6
--- /dev/null
+++ b/sys/v4l2/v4l2_calls.c
@@ -0,0 +1,925 @@
+/* GStreamer
+ *
+ * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * v4l2_calls.c - generic V4L2 calls handling
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef __sun
+/* Needed on older Solaris Nevada builds (72 at least) */
+#include <stropts.h>
+#include <sys/ioccom.h>
+#endif
+#include "v4l2_calls.h"
+#include "gstv4l2tuner.h"
+#if 0
+#include "gstv4l2xoverlay.h"
+#endif
+#include "gstv4l2colorbalance.h"
+
+#include "gstv4l2src.h"
+
+#ifdef HAVE_EXPERIMENTAL
+#include "gstv4l2sink.h"
+#endif
+
+#include "gst/gst-i18n-plugin.h"
+
+/* Those are ioctl calls */
+#ifndef V4L2_CID_HCENTER
+#define V4L2_CID_HCENTER V4L2_CID_HCENTER_DEPRECATED
+#endif
+#ifndef V4L2_CID_VCENTER
+#define V4L2_CID_VCENTER V4L2_CID_VCENTER_DEPRECATED
+#endif
+
+GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
+#define GST_CAT_DEFAULT v4l2_debug
+
+/******************************************************
+ * gst_v4l2_get_capabilities():
+ * get the device's capturing capabilities
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2_get_capabilities (GstV4l2Object * v4l2object)
+{
+ GstElement *e;
+
+ e = v4l2object->element;
+
+ GST_DEBUG_OBJECT (e, "getting capabilities");
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &v4l2object->vcap) < 0)
+ goto cap_failed;
+
+ GST_LOG_OBJECT (e, "driver: '%s'", v4l2object->vcap.driver);
+ GST_LOG_OBJECT (e, "card: '%s'", v4l2object->vcap.card);
+ GST_LOG_OBJECT (e, "bus_info: '%s'", v4l2object->vcap.bus_info);
+ GST_LOG_OBJECT (e, "version: %08x", v4l2object->vcap.version);
+ GST_LOG_OBJECT (e, "capabilites: %08x", v4l2object->vcap.capabilities);
+
+ return TRUE;
+
+ /* ERRORS */
+cap_failed:
+ {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Error getting capabilities for device '%s': "
+ "It isn't a v4l2 driver. Check if it is a v4l1 driver."),
+ v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
+
+
+/******************************************************
+ * gst_v4l2_empty_lists() and gst_v4l2_fill_lists():
+ * fill/empty the lists of enumerations
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+static gboolean
+gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
+{
+ gint n;
+
+ GstElement *e;
+
+ e = v4l2object->element;
+
+ GST_DEBUG_OBJECT (e, "getting enumerations");
+ GST_V4L2_CHECK_OPEN (v4l2object);
+
+ GST_DEBUG_OBJECT (e, " channels");
+ /* and now, the channels */
+ for (n = 0;; n++) {
+ struct v4l2_input input;
+ GstV4l2TunerChannel *v4l2channel;
+ GstTunerChannel *channel;
+
+ memset (&input, 0, sizeof (input));
+
+ input.index = n;
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENUMINPUT, &input) < 0) {
+ if (errno == EINVAL)
+ break; /* end of enumeration */
+ else {
+ GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
+ (_("Failed to query attributes of input %d in device %s"),
+ n, v4l2object->videodev),
+ ("Failed to get %d in input enumeration for %s. (%d - %s)",
+ n, v4l2object->videodev, errno, strerror (errno)));
+ return FALSE;
+ }
+ }
+
+ GST_LOG_OBJECT (e, " index: %d", input.index);
+ GST_LOG_OBJECT (e, " name: '%s'", input.name);
+ GST_LOG_OBJECT (e, " type: %08x", input.type);
+ GST_LOG_OBJECT (e, " audioset: %08x", input.audioset);
+ GST_LOG_OBJECT (e, " std: %016x", (guint) input.std);
+ GST_LOG_OBJECT (e, " status: %08x", input.status);
+
+ v4l2channel = g_object_new (GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
+ channel = GST_TUNER_CHANNEL (v4l2channel);
+ channel->label = g_strdup ((const gchar *) input.name);
+ channel->flags = GST_TUNER_CHANNEL_INPUT;
+ v4l2channel->index = n;
+
+ if (input.type == V4L2_INPUT_TYPE_TUNER) {
+ struct v4l2_tuner vtun;
+
+ v4l2channel->tuner = input.tuner;
+ channel->flags |= GST_TUNER_CHANNEL_FREQUENCY;
+
+ vtun.index = input.tuner;
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun) < 0) {
+ GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
+ (_("Failed to get setting of tuner %d on device '%s'."),
+ input.tuner, v4l2object->videodev), GST_ERROR_SYSTEM);
+ g_object_unref (G_OBJECT (channel));
+ return FALSE;
+ }
+
+ channel->freq_multiplicator =
+ 62.5 * ((vtun.capability & V4L2_TUNER_CAP_LOW) ? 1 : 1000);
+ channel->min_frequency = vtun.rangelow * channel->freq_multiplicator;
+ channel->max_frequency = vtun.rangehigh * channel->freq_multiplicator;
+ channel->min_signal = 0;
+ channel->max_signal = 0xffff;
+ }
+ if (input.audioset) {
+ /* we take the first. We don't care for
+ * the others for now */
+ while (!(input.audioset & (1 << v4l2channel->audio)))
+ v4l2channel->audio++;
+ channel->flags |= GST_TUNER_CHANNEL_AUDIO;
+ }
+
+ v4l2object->channels =
+ g_list_prepend (v4l2object->channels, (gpointer) channel);
+ }
+ v4l2object->channels = g_list_reverse (v4l2object->channels);
+
+ GST_DEBUG_OBJECT (e, " norms");
+ /* norms... */
+ for (n = 0;; n++) {
+ struct v4l2_standard standard = { 0, };
+ GstV4l2TunerNorm *v4l2norm;
+
+ GstTunerNorm *norm;
+
+ /* fill in defaults */
+ standard.frameperiod.numerator = 1;
+ standard.frameperiod.denominator = 0;
+ standard.index = n;
+
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENUMSTD, &standard) < 0) {
+ if (errno == EINVAL || errno == ENOTTY)
+ break; /* end of enumeration */
+ else {
+ GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
+ (_("Failed to query norm on device '%s'."),
+ v4l2object->videodev),
+ ("Failed to get attributes for norm %d on devide '%s'. (%d - %s)",
+ n, v4l2object->videodev, errno, strerror (errno)));
+ return FALSE;
+ }
+ }
+
+ GST_DEBUG_OBJECT (e, " '%s', fps: %d / %d",
+ standard.name, standard.frameperiod.denominator,
+ standard.frameperiod.numerator);
+
+ v4l2norm = g_object_new (GST_TYPE_V4L2_TUNER_NORM, NULL);
+ norm = GST_TUNER_NORM (v4l2norm);
+ norm->label = g_strdup ((const gchar *) standard.name);
+ gst_value_set_fraction (&norm->framerate,
+ standard.frameperiod.denominator, standard.frameperiod.numerator);
+ v4l2norm->index = standard.id;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "index=%08x, label=%s",
+ (unsigned int) v4l2norm->index, norm->label);
+
+ v4l2object->norms = g_list_prepend (v4l2object->norms, (gpointer) norm);
+ }
+ v4l2object->norms = g_list_reverse (v4l2object->norms);
+
+ GST_DEBUG_OBJECT (e, " controls+menus");
+
+ /* and lastly, controls+menus (if appropriate) */
+ for (n = V4L2_CID_BASE;; n++) {
+ struct v4l2_queryctrl control = { 0, };
+ GstV4l2ColorBalanceChannel *v4l2channel;
+ GstColorBalanceChannel *channel;
+
+ /* when we reached the last official CID, continue with private CIDs */
+ if (n == V4L2_CID_LASTP1) {
+ GST_DEBUG_OBJECT (e, "checking private CIDs");
+ n = V4L2_CID_PRIVATE_BASE;
+ }
+ GST_DEBUG_OBJECT (e, "checking control %08x", n);
+
+ control.id = n;
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCTRL, &control) < 0) {
+ if (errno == EINVAL || errno == ENOTTY || errno == EIO) {
+ if (n < V4L2_CID_PRIVATE_BASE) {
+ GST_DEBUG_OBJECT (e, "skipping control %08x", n);
+ /* continue so that we also check private controls */
+ continue;
+ } else {
+ GST_DEBUG_OBJECT (e, "controls finished");
+ break;
+ }
+ } else {
+ GST_WARNING_OBJECT (e, "Failed querying control %d on device '%s'. "
+ "(%d - %s)", n, v4l2object->videodev, errno, strerror (errno));
+ continue;
+ }
+ }
+ if (control.flags & V4L2_CTRL_FLAG_DISABLED) {
+ GST_DEBUG_OBJECT (e, "skipping disabled control");
+ continue;
+ }
+
+ switch (n) {
+ case V4L2_CID_BRIGHTNESS:
+ case V4L2_CID_CONTRAST:
+ case V4L2_CID_SATURATION:
+ case V4L2_CID_HUE:
+ case V4L2_CID_BLACK_LEVEL:
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ case V4L2_CID_DO_WHITE_BALANCE:
+ case V4L2_CID_RED_BALANCE:
+ case V4L2_CID_BLUE_BALANCE:
+ case V4L2_CID_GAMMA:
+ case V4L2_CID_EXPOSURE:
+ case V4L2_CID_AUTOGAIN:
+ case V4L2_CID_GAIN:
+#ifdef V4L2_CID_SHARPNESS
+ case V4L2_CID_SHARPNESS:
+#endif
+ /* we only handle these for now (why?) */
+ break;
+ case V4L2_CID_HFLIP:
+ case V4L2_CID_VFLIP:
+ case V4L2_CID_HCENTER:
+ case V4L2_CID_VCENTER:
+#ifdef V4L2_CID_PAN_RESET
+ case V4L2_CID_PAN_RESET:
+#endif
+#ifdef V4L2_CID_TILT_RESET
+ case V4L2_CID_TILT_RESET:
+#endif
+ /* not handled here, handled by VideoOrientation interface */
+ control.id++;
+ break;
+ case V4L2_CID_AUDIO_VOLUME:
+ case V4L2_CID_AUDIO_BALANCE:
+ case V4L2_CID_AUDIO_BASS:
+ case V4L2_CID_AUDIO_TREBLE:
+ case V4L2_CID_AUDIO_MUTE:
+ case V4L2_CID_AUDIO_LOUDNESS:
+ /* FIXME: We should implement GstMixer interface */
+ /* fall through */
+ default:
+ GST_DEBUG_OBJECT (e,
+ "ControlID %s (%x) unhandled, FIXME", control.name, n);
+ control.id++;
+ break;
+ }
+ if (n != control.id)
+ continue;
+
+ GST_DEBUG_OBJECT (e, "Adding ControlID %s (%x)", control.name, n);
+ v4l2channel = g_object_new (GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, NULL);
+ channel = GST_COLOR_BALANCE_CHANNEL (v4l2channel);
+ channel->label = g_strdup ((const gchar *) control.name);
+ v4l2channel->id = n;
+
+#if 0
+ /* FIXME: it will be need just when handling private controls
+ *(currently none of base controls are of this type) */
+ if (control.type == V4L2_CTRL_TYPE_MENU) {
+ struct v4l2_querymenu menu, *mptr;
+
+ int i;
+
+ menu.id = n;
+ for (i = 0;; i++) {
+ menu.index = i;
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYMENU, &menu) < 0) {
+ if (errno == EINVAL)
+ break; /* end of enumeration */
+ else {
+ GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
+ (_("Failed getting controls attributes on device '%s'."),
+ v4l2object->videodev),
+ ("Failed to get %d in menu enumeration for %s. (%d - %s)",
+ n, v4l2object->videodev, errno, strerror (errno)));
+ return FALSE;
+ }
+ }
+ mptr = g_malloc (sizeof (menu));
+ memcpy (mptr, &menu, sizeof (menu));
+ menus = g_list_append (menus, mptr);
+ }
+ }
+ v4l2object->menus = g_list_append (v4l2object->menus, menus);
+#endif
+
+ switch (control.type) {
+ case V4L2_CTRL_TYPE_INTEGER:
+ channel->min_value = control.minimum;
+ channel->max_value = control.maximum;
+ break;
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ channel->min_value = FALSE;
+ channel->max_value = TRUE;
+ break;
+ default:
+ /* FIXME we should find out how to handle V4L2_CTRL_TYPE_BUTTON.
+ BUTTON controls like V4L2_CID_DO_WHITE_BALANCE can just be set (1) or
+ unset (0), but can't be queried */
+ GST_DEBUG_OBJECT (e,
+ "Control with non supported type %s (%x), type=%d",
+ control.name, n, control.type);
+ channel->min_value = channel->max_value = 0;
+ break;
+ }
+
+ v4l2object->colors =
+ g_list_prepend (v4l2object->colors, (gpointer) channel);
+ }
+ v4l2object->colors = g_list_reverse (v4l2object->colors);
+
+ GST_DEBUG_OBJECT (e, "done");
+ return TRUE;
+}
+
+
+static void
+gst_v4l2_empty_lists (GstV4l2Object * v4l2object)
+{
+ GST_DEBUG_OBJECT (v4l2object->element, "deleting enumerations");
+
+ g_list_foreach (v4l2object->channels, (GFunc) g_object_unref, NULL);
+ g_list_free (v4l2object->channels);
+ v4l2object->channels = NULL;
+
+ g_list_foreach (v4l2object->norms, (GFunc) g_object_unref, NULL);
+ g_list_free (v4l2object->norms);
+ v4l2object->norms = NULL;
+
+ g_list_foreach (v4l2object->colors, (GFunc) g_object_unref, NULL);
+ g_list_free (v4l2object->colors);
+ v4l2object->colors = NULL;
+}
+
+/******************************************************
+ * gst_v4l2_open():
+ * open the video device (v4l2object->videodev)
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2_open (GstV4l2Object * v4l2object)
+{
+ struct stat st;
+ int libv4l2_fd;
+ GstPollFD pollfd = GST_POLL_FD_INIT;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "Trying to open device %s",
+ v4l2object->videodev);
+
+ GST_V4L2_CHECK_NOT_OPEN (v4l2object);
+ GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);
+
+ /* be sure we have a device */
+ if (!v4l2object->videodev)
+ v4l2object->videodev = g_strdup ("/dev/video");
+
+ /* check if it is a device */
+ if (stat (v4l2object->videodev, &st) == -1)
+ goto stat_failed;
+
+ if (!S_ISCHR (st.st_mode))
+ goto no_device;
+
+ /* open the device */
+ v4l2object->video_fd =
+ open (v4l2object->videodev, O_RDWR /* | O_NONBLOCK */ );
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ goto not_open;
+
+ libv4l2_fd = v4l2_fd_open (v4l2object->video_fd,
+ V4L2_ENABLE_ENUM_FMT_EMULATION);
+ /* Note the v4l2_xxx functions are designed so that if they get passed an
+ unknown fd, the will behave exactly as their regular xxx counterparts, so
+ if v4l2_fd_open fails, we continue as normal (missing the libv4l2 custom
+ cam format to normal formats conversion). Chances are big we will still
+ fail then though, as normally v4l2_fd_open only fails if the device is not
+ a v4l2 device. */
+ if (libv4l2_fd != -1)
+ v4l2object->video_fd = libv4l2_fd;
+
+ v4l2object->can_poll_device = TRUE;
+
+ /* get capabilities, error will be posted */
+ if (!gst_v4l2_get_capabilities (v4l2object))
+ goto error;
+
+ /* do we need to be a capture device? */
+ if (GST_IS_V4L2SRC (v4l2object->element) &&
+ !(v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
+ goto not_capture;
+
+#ifdef HAVE_EXPERIMENTAL
+ if (GST_IS_V4L2SINK (v4l2object->element) &&
+ !(v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT))
+ goto not_output;
+#endif
+
+ /* create enumerations, posts errors. */
+ if (!gst_v4l2_fill_lists (v4l2object))
+ goto error;
+
+ GST_INFO_OBJECT (v4l2object->element,
+ "Opened device '%s' (%s) successfully",
+ v4l2object->vcap.card, v4l2object->videodev);
+
+ pollfd.fd = v4l2object->video_fd;
+ gst_poll_add_fd (v4l2object->poll, &pollfd);
+ gst_poll_fd_ctl_read (v4l2object->poll, &pollfd, TRUE);
+
+ return TRUE;
+
+ /* ERRORS */
+stat_failed:
+ {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
+ (_("Cannot identify device '%s'."), v4l2object->videodev),
+ GST_ERROR_SYSTEM);
+ goto error;
+ }
+no_device:
+ {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
+ (_("This isn't a device '%s'."), v4l2object->videodev),
+ GST_ERROR_SYSTEM);
+ goto error;
+ }
+not_open:
+ {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, OPEN_READ_WRITE,
+ (_("Could not open device '%s' for reading and writing."),
+ v4l2object->videodev), GST_ERROR_SYSTEM);
+ goto error;
+ }
+not_capture:
+ {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
+ (_("Device '%s' is not a capture device."),
+ v4l2object->videodev),
+ ("Capabilities: 0x%x", v4l2object->vcap.capabilities));
+ goto error;
+ }
+#ifdef HAVE_EXPERIMENTAL
+not_output:
+ {
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
+ (_("Device '%s' is not a output device."),
+ v4l2object->videodev),
+ ("Capabilities: 0x%x", v4l2object->vcap.capabilities));
+ goto error;
+ }
+#endif
+error:
+ {
+ if (GST_V4L2_IS_OPEN (v4l2object)) {
+ /* close device */
+ v4l2_close (v4l2object->video_fd);
+ v4l2object->video_fd = -1;
+ }
+ /* empty lists */
+ gst_v4l2_empty_lists (v4l2object);
+
+ return FALSE;
+ }
+}
+
+
+/******************************************************
+ * gst_v4l2_close():
+ * close the video device (v4l2object->video_fd)
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2_close (GstV4l2Object * v4l2object)
+{
+ GstPollFD pollfd = GST_POLL_FD_INIT;
+ GST_DEBUG_OBJECT (v4l2object->element, "Trying to close %s",
+ v4l2object->videodev);
+
+ GST_V4L2_CHECK_OPEN (v4l2object);
+ GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);
+
+ /* close device */
+ v4l2_close (v4l2object->video_fd);
+ pollfd.fd = v4l2object->video_fd;
+ gst_poll_remove_fd (v4l2object->poll, &pollfd);
+ v4l2object->video_fd = -1;
+
+ /* empty lists */
+ gst_v4l2_empty_lists (v4l2object);
+
+ return TRUE;
+}
+
+
+/******************************************************
+ * gst_v4l2_get_norm()
+ * Get the norm of the current device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2_get_norm (GstV4l2Object * v4l2object, v4l2_std_id * norm)
+{
+ GST_DEBUG_OBJECT (v4l2object->element, "getting norm");
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_STD, norm) < 0)
+ goto std_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+std_failed:
+ {
+ GST_DEBUG ("Failed to get the current norm for device %s",
+ v4l2object->videodev);
+ return FALSE;
+ }
+}
+
+
+/******************************************************
+ * gst_v4l2_set_norm()
+ * Set the norm of the current device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2_set_norm (GstV4l2Object * v4l2object, v4l2_std_id norm)
+{
+ GST_DEBUG_OBJECT (v4l2object->element, "trying to set norm to "
+ "%" G_GINT64_MODIFIER "x", (guint64) norm);
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_STD, &norm) < 0)
+ goto std_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+std_failed:
+ {
+ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to set norm for device '%s'."),
+ v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
+
+/******************************************************
+ * gst_v4l2_get_frequency():
+ * get the current frequency
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2_get_frequency (GstV4l2Object * v4l2object,
+ gint tunernum, gulong * frequency)
+{
+ struct v4l2_frequency freq = { 0, };
+
+ GstTunerChannel *channel;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "getting current tuner frequency");
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ channel = gst_tuner_get_channel (GST_TUNER (v4l2object->element));
+
+ freq.tuner = tunernum;
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0)
+ goto freq_failed;
+
+ *frequency = freq.frequency * channel->freq_multiplicator;
+
+ return TRUE;
+
+ /* ERRORS */
+freq_failed:
+ {
+ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to get current tuner frequency for device '%s'."),
+ v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
+
+
+/******************************************************
+ * gst_v4l2_set_frequency():
+ * set frequency
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2_set_frequency (GstV4l2Object * v4l2object,
+ gint tunernum, gulong frequency)
+{
+ struct v4l2_frequency freq = { 0, };
+
+ GstTunerChannel *channel;
+
+ GST_DEBUG_OBJECT (v4l2object->element,
+ "setting current tuner frequency to %lu", frequency);
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ channel = gst_tuner_get_channel (GST_TUNER (v4l2object->element));
+
+ freq.tuner = tunernum;
+ /* fill in type - ignore error */
+ v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq);
+ freq.frequency = frequency / channel->freq_multiplicator;
+
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0)
+ goto freq_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+freq_failed:
+ {
+ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to set current tuner frequency for device '%s' to %lu Hz."),
+ v4l2object->videodev, frequency), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
+
+/******************************************************
+ * gst_v4l2_signal_strength():
+ * get the strength of the signal on the current input
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2_signal_strength (GstV4l2Object * v4l2object,
+ gint tunernum, gulong * signal_strength)
+{
+ struct v4l2_tuner tuner = { 0, };
+
+ GST_DEBUG_OBJECT (v4l2object->element, "trying to get signal strength");
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ tuner.index = tunernum;
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &tuner) < 0)
+ goto tuner_failed;
+
+ *signal_strength = tuner.signal;
+
+ return TRUE;
+
+ /* ERRORS */
+tuner_failed:
+ {
+ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to get signal strength for device '%s'."),
+ v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
+
+/******************************************************
+ * gst_v4l2_get_attribute():
+ * try to get the value of one specific attribute
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2_get_attribute (GstV4l2Object * v4l2object,
+ int attribute_num, int *value)
+{
+ struct v4l2_control control = { 0, };
+
+ GST_DEBUG_OBJECT (v4l2object->element, "getting value of attribute %d",
+ attribute_num);
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ control.id = attribute_num;
+
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
+ goto ctrl_failed;
+
+ *value = control.value;
+
+ return TRUE;
+
+ /* ERRORS */
+ctrl_failed:
+ {
+ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to get value for control %d on device '%s'."),
+ attribute_num, v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
+
+
+/******************************************************
+ * gst_v4l2_set_attribute():
+ * try to set the value of one specific attribute
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2_set_attribute (GstV4l2Object * v4l2object,
+ int attribute_num, const int value)
+{
+ struct v4l2_control control = { 0, };
+
+ GST_DEBUG_OBJECT (v4l2object->element, "setting value of attribute %d to %d",
+ attribute_num, value);
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ control.id = attribute_num;
+ control.value = value;
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0)
+ goto ctrl_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+ctrl_failed:
+ {
+ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to set value %d for control %d on device '%s'."),
+ value, attribute_num, v4l2object->videodev), GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+}
+
+gboolean
+gst_v4l2_get_input (GstV4l2Object * v4l2object, gint * input)
+{
+ gint n;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "trying to get input");
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_INPUT, &n) < 0)
+ goto input_failed;
+
+ *input = n;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "input: %d", n);
+
+ return TRUE;
+
+ /* ERRORS */
+input_failed:
+ if (v4l2object->vcap.capabilities & V4L2_CAP_TUNER) {
+ /* only give a warning message if driver actually claims to have tuner
+ * support
+ */
+ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to get current input on device '%s'. May be it is a radio device"), v4l2object->videodev), GST_ERROR_SYSTEM);
+ }
+ return FALSE;
+}
+
+gboolean
+gst_v4l2_set_input (GstV4l2Object * v4l2object, gint input)
+{
+ GST_DEBUG_OBJECT (v4l2object->element, "trying to set input to %d", input);
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_INPUT, &input) < 0)
+ goto input_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+input_failed:
+ if (v4l2object->vcap.capabilities & V4L2_CAP_TUNER) {
+ /* only give a warning message if driver actually claims to have tuner
+ * support
+ */
+ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to set input %d on device %s."),
+ input, v4l2object->videodev), GST_ERROR_SYSTEM);
+ }
+ return FALSE;
+}
+
+gboolean
+gst_v4l2_get_output (GstV4l2Object * v4l2object, gint * output)
+{
+ gint n;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "trying to get output");
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_OUTPUT, &n) < 0)
+ goto output_failed;
+
+ *output = n;
+
+ GST_DEBUG_OBJECT (v4l2object->element, "output: %d", n);
+
+ return TRUE;
+
+ /* ERRORS */
+output_failed:
+ if (v4l2object->vcap.capabilities & V4L2_CAP_TUNER) {
+ /* only give a warning message if driver actually claims to have tuner
+ * support
+ */
+ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to get current output on device '%s'. May be it is a radio device"), v4l2object->videodev), GST_ERROR_SYSTEM);
+ }
+ return FALSE;
+}
+
+gboolean
+gst_v4l2_set_output (GstV4l2Object * v4l2object, gint output)
+{
+ GST_DEBUG_OBJECT (v4l2object->element, "trying to set output to %d", output);
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_OUTPUT, &output) < 0)
+ goto output_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+output_failed:
+ if (v4l2object->vcap.capabilities & V4L2_CAP_TUNER) {
+ /* only give a warning message if driver actually claims to have tuner
+ * support
+ */
+ GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
+ (_("Failed to set output %d on device %s."),
+ output, v4l2object->videodev), GST_ERROR_SYSTEM);
+ }
+ return FALSE;
+}
diff --git a/sys/v4l2/v4l2_calls.h b/sys/v4l2/v4l2_calls.h
new file mode 100644
index 0000000..d2e2c72
--- /dev/null
+++ b/sys/v4l2/v4l2_calls.h
@@ -0,0 +1,142 @@
+/* GStreamer
+ *
+ * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * v4l2_calls.h - generic V4L2 calls handling
+ *
+ * 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.
+ */
+
+#ifndef __V4L2_CALLS_H__
+#define __V4L2_CALLS_H__
+
+#include "gstv4l2object.h"
+
+#ifdef HAVE_LIBV4L2
+# include <libv4l2.h>
+#else
+# include <sys/ioctl.h>
+# include <linux/videodev2.h>
+# define v4l2_fd_open(fd, flags) (fd)
+# define v4l2_close close
+# define v4l2_dup dup
+# define v4l2_ioctl ioctl
+# define v4l2_read read
+# define v4l2_mmap mmap
+# define v4l2_munmap munmap
+#endif
+
+/* simple check whether the device is open */
+#define GST_V4L2_IS_OPEN(v4l2object) \
+ (v4l2object->video_fd > 0)
+
+/* check whether the device is 'active' */
+#define GST_V4L2_IS_ACTIVE(v4l2object) \
+ (v4l2object->buffer != NULL)
+
+#define GST_V4L2_IS_OVERLAY(v4l2object) \
+ (v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
+
+/* checks whether the current v4lv4l2object has already been open()'ed or not */
+#define GST_V4L2_CHECK_OPEN(v4l2object) \
+ if (!GST_V4L2_IS_OPEN(v4l2object)) \
+ { \
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS, \
+ (_("Device is not open.")), (NULL)); \
+ return FALSE; \
+ }
+
+/* checks whether the current v4lv4l2object is close()'ed or whether it is still open */
+#define GST_V4L2_CHECK_NOT_OPEN(v4l2object) \
+ if (GST_V4L2_IS_OPEN(v4l2object)) \
+ { \
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS, \
+ (_("Device is open.")), (NULL)); \
+ return FALSE; \
+ }
+
+/* checks whether the current v4lv4l2object does video overlay */
+#define GST_V4L2_CHECK_OVERLAY(v4l2object) \
+ if (!GST_V4L2_IS_OVERLAY(v4l2object)) \
+ { \
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS, \
+ (NULL), ("Device cannot handle overlay")); \
+ return FALSE; \
+ }
+
+/* checks whether we're in capture mode or not */
+#define GST_V4L2_CHECK_ACTIVE(v4l2object) \
+ if (!GST_V4L2_IS_ACTIVE(v4l2object)) \
+ { \
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS, \
+ (NULL), ("Device is not in streaming mode")); \
+ return FALSE; \
+ }
+
+/* checks whether we're out of capture mode or not */
+#define GST_V4L2_CHECK_NOT_ACTIVE(v4l2object) \
+ if (GST_V4L2_IS_ACTIVE(v4l2object)) \
+ { \
+ GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS, \
+ (NULL), ("Device is in streaming mode")); \
+ return FALSE; \
+ }
+
+
+/* open/close the device */
+gboolean gst_v4l2_open (GstV4l2Object *v4l2object);
+gboolean gst_v4l2_close (GstV4l2Object *v4l2object);
+
+/* norm/input/output */
+gboolean gst_v4l2_get_norm (GstV4l2Object *v4l2object,
+ v4l2_std_id *norm);
+gboolean gst_v4l2_set_norm (GstV4l2Object *v4l2object,
+ v4l2_std_id norm);
+gboolean gst_v4l2_get_input (GstV4l2Object * v4l2object,
+ gint * input);
+gboolean gst_v4l2_set_input (GstV4l2Object * v4l2object,
+ gint input);
+gboolean gst_v4l2_get_output (GstV4l2Object *v4l2object,
+ gint *output);
+gboolean gst_v4l2_set_output (GstV4l2Object *v4l2object,
+ gint output);
+
+/* frequency control */
+gboolean gst_v4l2_get_frequency (GstV4l2Object *v4l2object,
+ gint tunernum,
+ gulong *frequency);
+gboolean gst_v4l2_set_frequency (GstV4l2Object *v4l2object,
+ gint tunernum,
+ gulong frequency);
+gboolean gst_v4l2_signal_strength (GstV4l2Object *v4l2object,
+ gint tunernum,
+ gulong *signal);
+
+/* attribute control */
+gboolean gst_v4l2_get_attribute (GstV4l2Object *v4l2object,
+ int attribute,
+ int *value);
+gboolean gst_v4l2_set_attribute (GstV4l2Object *v4l2object,
+ int attribute,
+ const int value);
+
+gboolean gst_v4l2_get_capabilities (GstV4l2Object * v4l2object);
+
+
+#define LOG_CAPS(obj, caps) GST_DEBUG_OBJECT (obj, "%s: %" GST_PTR_FORMAT, #caps, caps)
+
+#endif /* __V4L2_CALLS_H__ */
diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c
new file mode 100644
index 0000000..bfa5589
--- /dev/null
+++ b/sys/v4l2/v4l2src_calls.c
@@ -0,0 +1,434 @@
+/* GStreamer
+ *
+ * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * v4l2src.c - system calls
+ *
+ * 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 <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+#include "v4l2src_calls.h"
+#include <sys/time.h>
+#include <unistd.h>
+#ifdef __sun
+/* Needed on older Solaris Nevada builds (72 at least) */
+#include <stropts.h>
+#include <sys/ioccom.h>
+#endif
+
+#include "gstv4l2tuner.h"
+#include "gstv4l2bufferpool.h"
+
+#include "gst/gst-i18n-plugin.h"
+
+#define GST_CAT_DEFAULT v4l2src_debug
+GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
+
+/* lalala... */
+#define GST_V4L2_SET_ACTIVE(element) (element)->buffer = GINT_TO_POINTER (-1)
+#define GST_V4L2_SET_INACTIVE(element) (element)->buffer = NULL
+
+/* On some systems MAP_FAILED seems to be missing */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((caddr_t) -1)
+#endif
+
+
+/* Local functions */
+
+static gboolean
+gst_v4l2src_buffer_pool_activate (GstV4l2BufferPool * pool,
+ GstV4l2Src * v4l2src)
+{
+ GstV4l2Buffer *buf;
+
+ while ((buf = gst_v4l2_buffer_pool_get (pool, FALSE)) != NULL)
+ if (!gst_v4l2_buffer_pool_qbuf (pool, buf))
+ goto queue_failed;
+
+ return TRUE;
+
+ /* ERRORS */
+queue_failed:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+ (_("Could not enqueue buffers in device '%s'."),
+ v4l2src->v4l2object->videodev),
+ ("enqueing buffer %d/%d failed: %s",
+ buf->vbuffer.index, v4l2src->num_buffers, g_strerror (errno)));
+ return FALSE;
+ }
+}
+
+/******************************************************
+ * gst_v4l2src_grab_frame ():
+ * grab a frame for capturing
+ * return value: GST_FLOW_OK, GST_FLOW_WRONG_STATE or GST_FLOW_ERROR
+ ******************************************************/
+GstFlowReturn
+gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
+{
+#define NUM_TRIALS 50
+ GstV4l2Object *v4l2object;
+ GstV4l2BufferPool *pool;
+ gint32 trials = NUM_TRIALS;
+ GstBuffer *pool_buffer;
+ gboolean need_copy;
+ gint ret;
+
+ v4l2object = v4l2src->v4l2object;
+ pool = v4l2src->pool;
+ if (!pool)
+ goto no_buffer_pool;
+
+ GST_DEBUG_OBJECT (v4l2src, "grab frame");
+
+ for (;;) {
+ if (v4l2object->can_poll_device) {
+ ret = gst_poll_wait (v4l2object->poll, GST_CLOCK_TIME_NONE);
+ if (G_UNLIKELY (ret < 0)) {
+ if (errno == EBUSY)
+ goto stopped;
+ if (errno == ENXIO) {
+ GST_DEBUG_OBJECT (v4l2src,
+ "v4l2 device doesn't support polling. Disabling");
+ v4l2object->can_poll_device = FALSE;
+ } else {
+ if (errno != EAGAIN && errno != EINTR)
+ goto select_error;
+ }
+ }
+ }
+
+ pool_buffer = GST_BUFFER (gst_v4l2_buffer_pool_dqbuf (pool));
+ if (pool_buffer)
+ break;
+
+ GST_WARNING_OBJECT (pool->v4l2elem, "trials=%d", trials);
+
+ /* if the sync() got interrupted, we can retry */
+ switch (errno) {
+ case EINVAL:
+ case ENOMEM:
+ /* fatal */
+ return GST_FLOW_ERROR;
+
+ case EAGAIN:
+ case EIO:
+ case EINTR:
+ default:
+ /* try again, until too many trials */
+ break;
+ }
+
+ /* check nr. of attempts to capture */
+ if (--trials == -1) {
+ goto too_many_trials;
+ }
+ }
+
+ /* if we are handing out the last buffer in the pool, we need to make a
+ * copy and bring the buffer back in the pool. */
+ need_copy = v4l2src->always_copy
+ || !gst_v4l2_buffer_pool_available_buffers (pool);
+
+ if (G_UNLIKELY (need_copy)) {
+ if (!v4l2src->always_copy) {
+ GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, v4l2src,
+ "running out of buffers, making a copy to reuse current one");
+ }
+ *buf = gst_buffer_copy (pool_buffer);
+ GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY);
+ /* this will requeue */
+ gst_buffer_unref (pool_buffer);
+ } else {
+ *buf = pool_buffer;
+ }
+ /* we set the buffer metadata in gst_v4l2src_create() */
+
+ return GST_FLOW_OK;
+
+ /* ERRORS */
+no_buffer_pool:
+ {
+ GST_DEBUG ("no buffer pool");
+ return GST_FLOW_WRONG_STATE;
+ }
+select_error:
+ {
+ GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, READ, (NULL),
+ ("select error %d: %s (%d)", ret, g_strerror (errno), errno));
+ return GST_FLOW_ERROR;
+ }
+stopped:
+ {
+ GST_DEBUG ("stop called");
+ return GST_FLOW_WRONG_STATE;
+ }
+too_many_trials:
+ {
+ GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, FAILED,
+ (_("Failed trying to get video frames from device '%s'."),
+ v4l2object->videodev),
+ (_("Failed after %d tries. device %s. system error: %s"),
+ NUM_TRIALS, v4l2object->videodev, g_strerror (errno)));
+ return GST_FLOW_ERROR;
+ }
+}
+
+/******************************************************
+ * gst_v4l2src_set_capture():
+ * set capture parameters
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat,
+ guint32 width, guint32 height, gboolean interlaced,
+ guint fps_n, guint fps_d)
+{
+ gint fd = v4l2src->v4l2object->video_fd;
+ struct v4l2_streamparm stream;
+
+ if (pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G'))
+ return TRUE;
+
+ if (!gst_v4l2_object_set_format (v4l2src->v4l2object, pixelformat, width,
+ height, interlaced)) {
+ /* error already reported */
+ return FALSE;
+ }
+
+ /* Is there a reason we require the caller to always specify a framerate? */
+ GST_DEBUG_OBJECT (v4l2src, "Desired framerate: %u/%u", fps_n, fps_d);
+
+ memset (&stream, 0x00, sizeof (struct v4l2_streamparm));
+ stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (v4l2_ioctl (fd, VIDIOC_G_PARM, &stream) < 0) {
+ GST_ELEMENT_WARNING (v4l2src, RESOURCE, SETTINGS,
+ (_("Could not get parameters on device '%s'"),
+ v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
+ goto done;
+ }
+
+ /* We used to skip frame rate setup if the camera was already setup
+ with the requested frame rate. This breaks some cameras though,
+ causing them to not output data (several models of Thinkpad cameras
+ have this problem at least).
+ So, don't skip. */
+
+ /* We want to change the frame rate, so check whether we can. Some cheap USB
+ * cameras don't have the capability */
+ if ((stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
+ GST_DEBUG_OBJECT (v4l2src, "Not setting framerate (not supported)");
+ goto done;
+ }
+
+ GST_LOG_OBJECT (v4l2src, "Setting framerate to %u/%u", fps_n, fps_d);
+
+ /* Note: V4L2 wants the frame interval, we have the frame rate */
+ stream.parm.capture.timeperframe.numerator = fps_d;
+ stream.parm.capture.timeperframe.denominator = fps_n;
+
+ /* some cheap USB cam's won't accept any change */
+ if (v4l2_ioctl (fd, VIDIOC_S_PARM, &stream) < 0) {
+ GST_ELEMENT_WARNING (v4l2src, RESOURCE, SETTINGS,
+ (_("Video input device did not accept new frame rate setting.")),
+ GST_ERROR_SYSTEM);
+ goto done;
+ }
+
+ v4l2src->fps_n = fps_n;
+ v4l2src->fps_d = fps_d;
+
+ /* if we have a framerate pre-calculate duration */
+ if (fps_n > 0 && fps_d > 0) {
+ v4l2src->duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
+ } else {
+ v4l2src->duration = GST_CLOCK_TIME_NONE;
+ }
+
+ GST_INFO_OBJECT (v4l2src,
+ "Set framerate to %u/%u and duration to %" GST_TIME_FORMAT, fps_n, fps_d,
+ GST_TIME_ARGS (v4l2src->duration));
+done:
+
+ return TRUE;
+}
+
+/******************************************************
+ * gst_v4l2src_capture_init():
+ * initialize the capture system
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_init (GstV4l2Src * v4l2src, GstCaps * caps)
+{
+ GST_DEBUG_OBJECT (v4l2src, "initializing the capture system");
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_V4L2_CHECK_NOT_ACTIVE (v4l2src->v4l2object);
+
+ if (v4l2src->v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
+
+ /* Map the buffers */
+ GST_LOG_OBJECT (v4l2src, "initiating buffer pool");
+
+ if (!(v4l2src->pool = gst_v4l2_buffer_pool_new (GST_ELEMENT (v4l2src),
+ v4l2src->v4l2object->video_fd,
+ v4l2src->num_buffers, caps, TRUE, V4L2_BUF_TYPE_VIDEO_CAPTURE)))
+ goto buffer_pool_new_failed;
+
+ GST_INFO_OBJECT (v4l2src, "capturing buffers via mmap()");
+ v4l2src->use_mmap = TRUE;
+
+ if (v4l2src->num_buffers != v4l2src->pool->buffer_count) {
+ v4l2src->num_buffers = v4l2src->pool->buffer_count;
+ g_object_notify (G_OBJECT (v4l2src), "queue-size");
+ }
+
+ } else if (v4l2src->v4l2object->vcap.capabilities & V4L2_CAP_READWRITE) {
+ GST_INFO_OBJECT (v4l2src, "capturing buffers via read()");
+ v4l2src->use_mmap = FALSE;
+ v4l2src->pool = NULL;
+ } else {
+ goto no_supported_capture_method;
+ }
+
+ GST_V4L2_SET_ACTIVE (v4l2src->v4l2object);
+
+ return TRUE;
+
+ /* ERRORS */
+buffer_pool_new_failed:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+ (_("Could not map buffers from device '%s'"),
+ v4l2src->v4l2object->videodev),
+ ("Failed to create buffer pool: %s", g_strerror (errno)));
+ return FALSE;
+ }
+no_supported_capture_method:
+ {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+ (_("The driver of device '%s' does not support any known capture "
+ "method."), v4l2src->v4l2object->videodev), (NULL));
+ return FALSE;
+ }
+}
+
+
+/******************************************************
+ * gst_v4l2src_capture_start():
+ * start streaming capture
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_start (GstV4l2Src * v4l2src)
+{
+ GST_DEBUG_OBJECT (v4l2src, "starting the capturing");
+ //GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_V4L2_CHECK_ACTIVE (v4l2src->v4l2object);
+
+ v4l2src->quit = FALSE;
+
+ if (v4l2src->use_mmap) {
+ if (!gst_v4l2src_buffer_pool_activate (v4l2src->pool, v4l2src)) {
+ return FALSE;
+ }
+
+ if (!gst_v4l2_object_start_streaming (v4l2src->v4l2object)) {
+ return FALSE;
+ }
+ }
+
+ v4l2src->is_capturing = TRUE;
+
+ return TRUE;
+}
+
+/******************************************************
+ * gst_v4l2src_capture_stop():
+ * stop streaming capture
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_stop (GstV4l2Src * v4l2src)
+{
+ GST_DEBUG_OBJECT (v4l2src, "stopping capturing");
+
+ if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) {
+ goto done;
+ }
+ if (!GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
+ goto done;
+ }
+
+ if (v4l2src->use_mmap) {
+ /* we actually need to sync on all queued buffers but not
+ * on the non-queued ones */
+ if (!gst_v4l2_object_stop_streaming (v4l2src->v4l2object)) {
+ return FALSE;
+ }
+ }
+
+done:
+
+ /* make an optional pending wait stop */
+ v4l2src->quit = TRUE;
+ v4l2src->is_capturing = FALSE;
+
+ return TRUE;
+}
+
+/******************************************************
+ * gst_v4l2src_capture_deinit():
+ * deinitialize the capture system
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
+{
+ GST_DEBUG_OBJECT (v4l2src, "deinitting capture system");
+
+ if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) {
+ return TRUE;
+ }
+ if (!GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
+ return TRUE;
+ }
+
+ if (v4l2src->pool) {
+ gst_v4l2_buffer_pool_destroy (v4l2src->pool);
+ v4l2src->pool = NULL;
+ }
+
+ GST_V4L2_SET_INACTIVE (v4l2src->v4l2object);
+
+ return TRUE;
+}
diff --git a/sys/v4l2/v4l2src_calls.h b/sys/v4l2/v4l2src_calls.h
new file mode 100644
index 0000000..7091918
--- /dev/null
+++ b/sys/v4l2/v4l2src_calls.h
@@ -0,0 +1,46 @@
+/* GStreamer
+ *
+ * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * 2006 Edgard Lima <edgard.lima@indt.org.br>
+ *
+ * v4l2src.h - system calls
+ *
+ * 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.
+ */
+
+#ifndef __V4L2SRC_CALLS_H__
+#define __V4L2SRC_CALLS_H__
+
+#include "gstv4l2src.h"
+#include "v4l2_calls.h"
+
+gboolean gst_v4l2src_get_capture (GstV4l2Src * v4l2src);
+gboolean gst_v4l2src_set_capture (GstV4l2Src * v4l2src,
+ guint32 pixelformat,
+ guint32 width, guint32 height,
+ gboolean interlaced,
+ guint32 fps_n, guint32 fps_d);
+
+gboolean gst_v4l2src_capture_init (GstV4l2Src * v4l2src, GstCaps *caps);
+gboolean gst_v4l2src_capture_start (GstV4l2Src * v4l2src);
+
+GstFlowReturn gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer **buf);
+
+gboolean gst_v4l2src_capture_stop (GstV4l2Src * v4l2src);
+gboolean gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src);
+
+
+#endif /* __V4L2SRC_CALLS_H__ */
diff --git a/sys/waveform/Makefile.am b/sys/waveform/Makefile.am
new file mode 100644
index 0000000..a9562a8
--- /dev/null
+++ b/sys/waveform/Makefile.am
@@ -0,0 +1,20 @@
+plugin_LTLIBRARIES = libgstwaveformsink.la
+
+# FIXME: Replace DIRECTSOUND CFLAGS+LIBS with waveform related ones and fix
+# the configure.ac + sys/Makefile.am to get this stuff building in MingW
+# For now, it's just disted for use in the VS builds.
+
+libgstwaveformsink_la_SOURCES = gstwaveformsink.c gstwaveformplugin.c
+libgstwaveformsink_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \
+ $(GST_PLUGINS_BASE_CFLAGS) $(DIRECTSOUND_CFLAGS)
+libgstwaveformsink_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstaudio-$(GST_MAJORMINOR) -lgstinterfaces-$(GST_MAJORMINOR) \
+ $(GST_BASE_LIBS) \
+ $(GST_LIBS) \
+ $(DIRECTSOUND_LIBS)
+libgstwaveformsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(DIRECTSOUND_LDFLAGS)
+libgstwaveformsink_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = gstwaveformsink.h
+
diff --git a/sys/waveform/Makefile.in b/sys/waveform/Makefile.in
new file mode 100644
index 0000000..efdf5e7
--- /dev/null
+++ b/sys/waveform/Makefile.in
@@ -0,0 +1,828 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sys/waveform
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
+ $(top_srcdir)/common/m4/as-auto-alt.m4 \
+ $(top_srcdir)/common/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/common/m4/as-gcc-inline-assembly.m4 \
+ $(top_srcdir)/common/m4/as-objc.m4 \
+ $(top_srcdir)/common/m4/as-python.m4 \
+ $(top_srcdir)/common/m4/as-scrub-include.m4 \
+ $(top_srcdir)/common/m4/as-version.m4 \
+ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
+ $(top_srcdir)/common/m4/gst-arch.m4 \
+ $(top_srcdir)/common/m4/gst-args.m4 \
+ $(top_srcdir)/common/m4/gst-check.m4 \
+ $(top_srcdir)/common/m4/gst-default.m4 \
+ $(top_srcdir)/common/m4/gst-dowhile.m4 \
+ $(top_srcdir)/common/m4/gst-error.m4 \
+ $(top_srcdir)/common/m4/gst-feature.m4 \
+ $(top_srcdir)/common/m4/gst-gettext.m4 \
+ $(top_srcdir)/common/m4/gst-glib2.m4 \
+ $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \
+ $(top_srcdir)/common/m4/gst-platform.m4 \
+ $(top_srcdir)/common/m4/gst-plugin-docs.m4 \
+ $(top_srcdir)/common/m4/gst-plugindir.m4 \
+ $(top_srcdir)/common/m4/gst-x11.m4 \
+ $(top_srcdir)/common/m4/gst.m4 \
+ $(top_srcdir)/common/m4/gtk-doc.m4 \
+ $(top_srcdir)/common/m4/orc.m4 $(top_srcdir)/common/m4/pkg.m4 \
+ $(top_srcdir)/m4/aalib.m4 $(top_srcdir)/m4/esd.m4 \
+ $(top_srcdir)/m4/gconf-2.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gst-fionread.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgstwaveformsink_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_libgstwaveformsink_la_OBJECTS = \
+ libgstwaveformsink_la-gstwaveformsink.lo \
+ libgstwaveformsink_la-gstwaveformplugin.lo
+libgstwaveformsink_la_OBJECTS = $(am_libgstwaveformsink_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libgstwaveformsink_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(libgstwaveformsink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(libgstwaveformsink_la_CFLAGS) $(CFLAGS) \
+ $(libgstwaveformsink_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libgstwaveformsink_la_SOURCES)
+DIST_SOURCES = $(libgstwaveformsink_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+AALIB_CFLAGS = @AALIB_CFLAGS@
+AALIB_CONFIG = @AALIB_CONFIG@
+AALIB_LIBS = @AALIB_LIBS@
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+ANNODEX_CFLAGS = @ANNODEX_CFLAGS@
+ANNODEX_LIBS = @ANNODEX_LIBS@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BZ2_LIBS = @BZ2_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_GOBJECT_CFLAGS = @CAIRO_GOBJECT_CFLAGS@
+CAIRO_GOBJECT_LIBS = @CAIRO_GOBJECT_LIBS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@
+DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@
+DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@
+DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@
+DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@
+DIRECTSOUND_CFLAGS = @DIRECTSOUND_CFLAGS@
+DIRECTSOUND_LDFLAGS = @DIRECTSOUND_LDFLAGS@
+DIRECTSOUND_LIBS = @DIRECTSOUND_LIBS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DV1394_CFLAGS = @DV1394_CFLAGS@
+DV1394_LIBS = @DV1394_LIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ERROR_CFLAGS = @ERROR_CFLAGS@
+ERROR_CXXFLAGS = @ERROR_CXXFLAGS@
+ESD_CFLAGS = @ESD_CFLAGS@
+ESD_CONFIG = @ESD_CONFIG@
+ESD_LIBS = @ESD_LIBS@
+EXEEXT = @EXEEXT@
+FFLAGS = @FFLAGS@
+FGREP = @FGREP@
+FLAC_CFLAGS = @FLAC_CFLAGS@
+FLAC_LIBS = @FLAC_LIBS@
+GCONFTOOL = @GCONFTOOL@
+GCONF_CFLAGS = @GCONF_CFLAGS@
+GCONF_LIBS = @GCONF_LIBS@
+GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+GCOV = @GCOV@
+GCOV_CFLAGS = @GCOV_CFLAGS@
+GCOV_LIBS = @GCOV_LIBS@
+GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@
+GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_PREFIX = @GLIB_PREFIX@
+GLIB_REQ = @GLIB_REQ@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@
+GSTPB_PREFIX = @GSTPB_PREFIX@
+GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@
+GST_BASE_CFLAGS = @GST_BASE_CFLAGS@
+GST_BASE_LIBS = @GST_BASE_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_CONTROLLER_CFLAGS = @GST_CONTROLLER_CFLAGS@
+GST_CONTROLLER_LIBS = @GST_CONTROLLER_LIBS@
+GST_CXXFLAGS = @GST_CXXFLAGS@
+GST_GDP_CFLAGS = @GST_GDP_CFLAGS@
+GST_GDP_LIBS = @GST_GDP_LIBS@
+GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@
+GST_LIBS = @GST_LIBS@
+GST_LICENSE = @GST_LICENSE@
+GST_LT_LDFLAGS = @GST_LT_LDFLAGS@
+GST_MAJORMINOR = @GST_MAJORMINOR@
+GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@
+GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@
+GST_PACKAGE_NAME = @GST_PACKAGE_NAME@
+GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@
+GST_PLUGINS_ALL = @GST_PLUGINS_ALL@
+GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@
+GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@
+GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@
+GST_PLUGINS_DIR = @GST_PLUGINS_DIR@
+GST_PLUGINS_SELECTED = @GST_PLUGINS_SELECTED@
+GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@
+GST_PREFIX = @GST_PREFIX@
+GST_TOOLS_DIR = @GST_TOOLS_DIR@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_X11_CFLAGS = @GTK_X11_CFLAGS@
+GTK_X11_LIBS = @GTK_X11_LIBS@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+HAVE_AVC1394 = @HAVE_AVC1394@
+HAVE_BZ2 = @HAVE_BZ2@
+HAVE_CXX = @HAVE_CXX@
+HAVE_DIRECTSOUND = @HAVE_DIRECTSOUND@
+HAVE_GCONFTOOL = @HAVE_GCONFTOOL@
+HAVE_ROM1394 = @HAVE_ROM1394@
+HAVE_SPEEX = @HAVE_SPEEX@
+HAVE_X = @HAVE_X@
+HAVE_XSHM = @HAVE_XSHM@
+HAVE_ZLIB = @HAVE_ZLIB@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JACK_0_120_1_CFLAGS = @JACK_0_120_1_CFLAGS@
+JACK_0_120_1_LIBS = @JACK_0_120_1_LIBS@
+JACK_1_9_7_CFLAGS = @JACK_1_9_7_CFLAGS@
+JACK_1_9_7_LIBS = @JACK_1_9_7_LIBS@
+JACK_CFLAGS = @JACK_CFLAGS@
+JACK_LIBS = @JACK_LIBS@
+JPEG_LIBS = @JPEG_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCACA_CFLAGS = @LIBCACA_CFLAGS@
+LIBCACA_LIBS = @LIBCACA_LIBS@
+LIBDV_CFLAGS = @LIBDV_CFLAGS@
+LIBDV_LIBS = @LIBDV_LIBS@
+LIBICONV = @LIBICONV@
+LIBIEC61883_CFLAGS = @LIBIEC61883_CFLAGS@
+LIBIEC61883_LIBS = @LIBIEC61883_LIBS@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBPNG_CFLAGS = @LIBPNG_CFLAGS@
+LIBPNG_LIBS = @LIBPNG_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBV4L2_CFLAGS = @LIBV4L2_CFLAGS@
+LIBV4L2_LIBS = @LIBV4L2_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCALEDIR = @LOCALEDIR@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJC_LDFLAGS = @OBJC_LDFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORCC = @ORCC@
+ORCC_FLAGS = @ORCC_FLAGS@
+ORC_CFLAGS = @ORC_CFLAGS@
+ORC_LIBS = @ORC_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@
+PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PLUGINDIR = @PLUGINDIR@
+POSUB = @POSUB@
+PROFILE_CFLAGS = @PROFILE_CFLAGS@
+PULSE_0_9_20_CFLAGS = @PULSE_0_9_20_CFLAGS@
+PULSE_0_9_20_LIBS = @PULSE_0_9_20_LIBS@
+PULSE_1_0_CFLAGS = @PULSE_1_0_CFLAGS@
+PULSE_1_0_LIBS = @PULSE_1_0_LIBS@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RAW1394_CFLAGS = @RAW1394_CFLAGS@
+RAW1394_LIBS = @RAW1394_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHOUT2_CFLAGS = @SHOUT2_CFLAGS@
+SHOUT2_LIBS = @SHOUT2_LIBS@
+SOUP_CFLAGS = @SOUP_CFLAGS@
+SOUP_LIBS = @SOUP_LIBS@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+TAGLIB_CFLAGS = @TAGLIB_CFLAGS@
+TAGLIB_CXXFLAGS = @TAGLIB_CXXFLAGS@
+TAGLIB_LIBS = @TAGLIB_LIBS@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VALGRIND_PATH = @VALGRIND_PATH@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
+WAVPACK_LIBS = @WAVPACK_LIBS@
+WIN32_LIBS = @WIN32_LIBS@
+XDAMAGE_CFLAGS = @XDAMAGE_CFLAGS@
+XDAMAGE_LIBS = @XDAMAGE_LIBS@
+XFIXES_CFLAGS = @XFIXES_CFLAGS@
+XFIXES_LIBS = @XFIXES_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+XMKMF = @XMKMF@
+XSHM_LIBS = @XSHM_LIBS@
+XVIDEO_LIBS = @XVIDEO_LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = libgstwaveformsink.la
+
+# FIXME: Replace DIRECTSOUND CFLAGS+LIBS with waveform related ones and fix
+# the configure.ac + sys/Makefile.am to get this stuff building in MingW
+# For now, it's just disted for use in the VS builds.
+libgstwaveformsink_la_SOURCES = gstwaveformsink.c gstwaveformplugin.c
+libgstwaveformsink_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \
+ $(GST_PLUGINS_BASE_CFLAGS) $(DIRECTSOUND_CFLAGS)
+
+libgstwaveformsink_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) \
+ -lgstaudio-$(GST_MAJORMINOR) -lgstinterfaces-$(GST_MAJORMINOR) \
+ $(GST_BASE_LIBS) \
+ $(GST_LIBS) \
+ $(DIRECTSOUND_LIBS)
+
+libgstwaveformsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(DIRECTSOUND_LDFLAGS)
+libgstwaveformsink_la_LIBTOOLFLAGS = --tag=disable-static
+noinst_HEADERS = gstwaveformsink.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sys/waveform/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu sys/waveform/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgstwaveformsink.la: $(libgstwaveformsink_la_OBJECTS) $(libgstwaveformsink_la_DEPENDENCIES) $(EXTRA_libgstwaveformsink_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgstwaveformsink_la_LINK) -rpath $(plugindir) $(libgstwaveformsink_la_OBJECTS) $(libgstwaveformsink_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstwaveformsink_la-gstwaveformplugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstwaveformsink_la-gstwaveformsink.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libgstwaveformsink_la-gstwaveformsink.lo: gstwaveformsink.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstwaveformsink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstwaveformsink_la_CFLAGS) $(CFLAGS) -MT libgstwaveformsink_la-gstwaveformsink.lo -MD -MP -MF $(DEPDIR)/libgstwaveformsink_la-gstwaveformsink.Tpo -c -o libgstwaveformsink_la-gstwaveformsink.lo `test -f 'gstwaveformsink.c' || echo '$(srcdir)/'`gstwaveformsink.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstwaveformsink_la-gstwaveformsink.Tpo $(DEPDIR)/libgstwaveformsink_la-gstwaveformsink.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstwaveformsink.c' object='libgstwaveformsink_la-gstwaveformsink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstwaveformsink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstwaveformsink_la_CFLAGS) $(CFLAGS) -c -o libgstwaveformsink_la-gstwaveformsink.lo `test -f 'gstwaveformsink.c' || echo '$(srcdir)/'`gstwaveformsink.c
+
+libgstwaveformsink_la-gstwaveformplugin.lo: gstwaveformplugin.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstwaveformsink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstwaveformsink_la_CFLAGS) $(CFLAGS) -MT libgstwaveformsink_la-gstwaveformplugin.lo -MD -MP -MF $(DEPDIR)/libgstwaveformsink_la-gstwaveformplugin.Tpo -c -o libgstwaveformsink_la-gstwaveformplugin.lo `test -f 'gstwaveformplugin.c' || echo '$(srcdir)/'`gstwaveformplugin.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstwaveformsink_la-gstwaveformplugin.Tpo $(DEPDIR)/libgstwaveformsink_la-gstwaveformplugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstwaveformplugin.c' object='libgstwaveformsink_la-gstwaveformplugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstwaveformsink_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstwaveformsink_la_CFLAGS) $(CFLAGS) -c -o libgstwaveformsink_la-gstwaveformplugin.lo `test -f 'gstwaveformplugin.c' || echo '$(srcdir)/'`gstwaveformplugin.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sys/waveform/gstwaveformplugin.c b/sys/waveform/gstwaveformplugin.c
new file mode 100644
index 0000000..0d7943e
--- /dev/null
+++ b/sys/waveform/gstwaveformplugin.c
@@ -0,0 +1,42 @@
+/* GStreamer
+* Copyright (C) 2005 Sebastien Moutte <sebastien@moutte.net>
+*
+* gstwaveformplugin.c:
+*
+* 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 "gstwaveformsink.h"
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ if (!gst_element_register (plugin, "waveformsink", GST_RANK_PRIMARY,
+ GST_TYPE_WAVEFORM_SINK))
+ return FALSE;
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "waveform",
+ "WaveForm win32 API plugin",
+ plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/waveform/gstwaveformsink.c b/sys/waveform/gstwaveformsink.c
new file mode 100644
index 0000000..0c59829
--- /dev/null
+++ b/sys/waveform/gstwaveformsink.c
@@ -0,0 +1,585 @@
+/* GStreamer
+* Copyright (C) 2005 Sebastien Moutte <sebastien@moutte.net>
+*
+* gstwaveformsink.c:
+*
+* 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-waveformsink
+ *
+ * This element lets you output sound using the Windows WaveForm API.
+ *
+ * Note that you should almost always use generic audio conversion elements
+ * like audioconvert and audioresample in front of an audiosink to make sure
+ * your pipeline works under all circumstances (those conversion elements will
+ * act in passthrough-mode if no conversion is necessary).
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * |[
+ * gst-launch -v audiotestsrc ! audioconvert ! volume volume=0.1 ! waveformsink
+ * ]| will output a sine wave (continuous beep sound) to your sound card (with
+ * a very low volume as precaution).
+ * |[
+ * gst-launch -v filesrc location=music.ogg ! decodebin ! audioconvert ! audioresample ! waveformsink
+ * ]| will play an Ogg/Vorbis audio file and output it.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstwaveformsink.h"
+
+GST_DEBUG_CATEGORY_STATIC (waveformsink_debug);
+
+static void gst_waveform_sink_base_init (gpointer g_class);
+static void gst_waveform_sink_class_init (GstWaveFormSinkClass * klass);
+static void gst_waveform_sink_init (GstWaveFormSink * wfsink,
+ GstWaveFormSinkClass * g_class);
+static void gst_waveform_sink_finalise (GObject * object);
+static void gst_waveform_sink_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_waveform_sink_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec);
+static GstCaps *gst_waveform_sink_getcaps (GstBaseSink * bsink);
+
+/************************************************************************/
+/* GstAudioSink functions */
+/************************************************************************/
+static gboolean gst_waveform_sink_prepare (GstAudioSink * asink,
+ GstRingBufferSpec * spec);
+static gboolean gst_waveform_sink_unprepare (GstAudioSink * asink);
+static gboolean gst_waveform_sink_open (GstAudioSink * asink);
+static gboolean gst_waveform_sink_close (GstAudioSink * asink);
+static guint gst_waveform_sink_write (GstAudioSink * asink, gpointer data,
+ guint length);
+static guint gst_waveform_sink_delay (GstAudioSink * asink);
+static void gst_waveform_sink_reset (GstAudioSink * asink);
+
+/************************************************************************/
+/* Utils */
+/************************************************************************/
+GstCaps *gst_waveform_sink_create_caps (gint rate, gint channels,
+ gint bits_per_sample);
+WAVEHDR *bufferpool_get_buffer (GstWaveFormSink * wfsink, gpointer data,
+ guint length);
+void CALLBACK waveOutProc (HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
+ DWORD_PTR dwParam1, DWORD_PTR dwParam2);
+
+static GstStaticPadTemplate waveformsink_sink_factory =
+ GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-int, "
+ "signed = (boolean) { TRUE, FALSE }, "
+ "width = (int) 16, "
+ "depth = (int) 16, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
+ "audio/x-raw-int, "
+ "signed = (boolean) { TRUE, FALSE }, "
+ "width = (int) 8, "
+ "depth = (int) 8, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]"));
+
+GST_BOILERPLATE (GstWaveFormSink, gst_waveform_sink, GstAudioSink,
+ GST_TYPE_AUDIO_SINK);
+
+static void
+gst_waveform_sink_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_set_details_simple (element_class, "WaveForm Audio Sink",
+ "Sink/Audio",
+ "Output to a sound card via WaveForm API",
+ "Sebastien Moutte <sebastien@moutte.net>");
+ gst_element_class_add_static_pad_template (element_class,
+ &waveformsink_sink_factory);
+}
+
+static void
+gst_waveform_sink_class_init (GstWaveFormSinkClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSinkClass *gstbasesink_class;
+ GstBaseAudioSinkClass *gstbaseaudiosink_class;
+ GstAudioSinkClass *gstaudiosink_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesink_class = (GstBaseSinkClass *) klass;
+ gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
+ gstaudiosink_class = (GstAudioSinkClass *) klass;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = gst_waveform_sink_finalise;
+ gobject_class->get_property = gst_waveform_sink_get_property;
+ gobject_class->set_property = gst_waveform_sink_set_property;
+
+ gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_waveform_sink_getcaps);
+
+ gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_waveform_sink_prepare);
+ gstaudiosink_class->unprepare =
+ GST_DEBUG_FUNCPTR (gst_waveform_sink_unprepare);
+ gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_waveform_sink_open);
+ gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_waveform_sink_close);
+ gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_waveform_sink_write);
+ gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_waveform_sink_delay);
+ gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_waveform_sink_reset);
+
+ GST_DEBUG_CATEGORY_INIT (waveformsink_debug, "waveformsink", 0,
+ "Waveform sink");
+}
+
+static void
+gst_waveform_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_waveform_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_waveform_sink_init (GstWaveFormSink * wfsink,
+ GstWaveFormSinkClass * g_class)
+{
+ /* initialize members */
+ wfsink->hwaveout = NULL;
+ wfsink->cached_caps = NULL;
+ wfsink->wave_buffers = NULL;
+ wfsink->write_buffer = 0;
+ wfsink->buffer_count = BUFFER_COUNT;
+ wfsink->buffer_size = BUFFER_SIZE;
+ wfsink->free_buffers_count = wfsink->buffer_count;
+ wfsink->bytes_in_queue = 0;
+
+ InitializeCriticalSection (&wfsink->critic_wave);
+}
+
+static void
+gst_waveform_sink_finalise (GObject * object)
+{
+ GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (object);
+
+ if (wfsink->cached_caps) {
+ gst_caps_unref (wfsink->cached_caps);
+ wfsink->cached_caps = NULL;
+ }
+
+ DeleteCriticalSection (&wfsink->critic_wave);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static GstCaps *
+gst_waveform_sink_getcaps (GstBaseSink * bsink)
+{
+ GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (bsink);
+ MMRESULT mmresult;
+ WAVEOUTCAPS wocaps;
+ GstCaps *caps, *caps_temp;
+
+ /* return the cached caps if already defined */
+ if (wfsink->cached_caps) {
+ return gst_caps_ref (wfsink->cached_caps);
+ }
+
+ /* get the default device caps */
+ mmresult = waveOutGetDevCaps (WAVE_MAPPER, &wocaps, sizeof (wocaps));
+ if (mmresult != MMSYSERR_NOERROR) {
+ waveOutGetErrorText (mmresult, wfsink->error_string, ERROR_LENGTH - 1);
+ GST_ELEMENT_ERROR (wfsink, RESOURCE, SETTINGS,
+ ("gst_waveform_sink_getcaps: waveOutGetDevCaps failed error=>%s",
+ wfsink->error_string), (NULL));
+ return NULL;
+ }
+
+ caps = gst_caps_new_empty ();
+
+ /* create a caps for all wave formats supported by the device
+ starting by the best quality format */
+ if (wocaps.dwFormats & WAVE_FORMAT_96S16) {
+ caps_temp = gst_waveform_sink_create_caps (96000, 2, 16);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_96S08) {
+ caps_temp = gst_waveform_sink_create_caps (96000, 2, 8);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_96M16) {
+ caps_temp = gst_waveform_sink_create_caps (96000, 1, 16);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_96M08) {
+ caps_temp = gst_waveform_sink_create_caps (96000, 1, 8);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_4S16) {
+ caps_temp = gst_waveform_sink_create_caps (44100, 2, 16);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_4S08) {
+ caps_temp = gst_waveform_sink_create_caps (44100, 2, 8);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_4M16) {
+ caps_temp = gst_waveform_sink_create_caps (44100, 1, 16);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_4M08) {
+ caps_temp = gst_waveform_sink_create_caps (44100, 1, 8);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_2S16) {
+ caps_temp = gst_waveform_sink_create_caps (22050, 2, 16);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_2S08) {
+ caps_temp = gst_waveform_sink_create_caps (22050, 2, 8);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_2M16) {
+ caps_temp = gst_waveform_sink_create_caps (22050, 1, 16);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_2M08) {
+ caps_temp = gst_waveform_sink_create_caps (22050, 1, 8);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_1S16) {
+ caps_temp = gst_waveform_sink_create_caps (11025, 2, 16);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_1S08) {
+ caps_temp = gst_waveform_sink_create_caps (11025, 2, 8);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_1M16) {
+ caps_temp = gst_waveform_sink_create_caps (11025, 1, 16);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+ if (wocaps.dwFormats & WAVE_FORMAT_1M08) {
+ caps_temp = gst_waveform_sink_create_caps (11025, 1, 8);
+ if (caps_temp) {
+ gst_caps_append (caps, caps_temp);
+ }
+ }
+
+ if (gst_caps_is_empty (caps)) {
+ gst_caps_unref (caps);
+ caps = NULL;
+ } else {
+ wfsink->cached_caps = gst_caps_ref (caps);
+ }
+
+ GST_CAT_LOG_OBJECT (waveformsink_debug, wfsink, "Returning caps %s",
+ gst_caps_to_string (caps));
+
+ return caps;
+}
+
+static gboolean
+gst_waveform_sink_open (GstAudioSink * asink)
+{
+ GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink);
+
+ /* nothing to do here as the device needs to be opened with the format we will use */
+
+ return TRUE;
+}
+
+static gboolean
+gst_waveform_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
+{
+ GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink);
+ WAVEFORMATEX wfx;
+ MMRESULT mmresult;
+ guint index;
+
+ /* setup waveformex struture with the input ringbuffer specs */
+ memset (&wfx, 0, sizeof (wfx));
+ wfx.cbSize = 0;
+ wfx.wFormatTag = WAVE_FORMAT_PCM;
+ wfx.nChannels = spec->channels;
+ wfx.nSamplesPerSec = spec->rate;
+ wfx.wBitsPerSample = (spec->bytes_per_sample * 8) / wfx.nChannels;
+ wfx.nBlockAlign = spec->bytes_per_sample;
+ wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+
+ /* save bytes per sample to use it in delay */
+ wfsink->bytes_per_sample = spec->bytes_per_sample;
+
+ /* open the default audio device with the given caps */
+ mmresult = waveOutOpen (&wfsink->hwaveout, WAVE_MAPPER,
+ &wfx, (DWORD_PTR) waveOutProc, (DWORD_PTR) wfsink, CALLBACK_FUNCTION);
+ if (mmresult != MMSYSERR_NOERROR) {
+ waveOutGetErrorText (mmresult, wfsink->error_string, ERROR_LENGTH - 1);
+ GST_ELEMENT_ERROR (wfsink, RESOURCE, OPEN_WRITE,
+ ("gst_waveform_sink_prepare: waveOutOpen failed error=>%s",
+ wfsink->error_string), (NULL));
+ return FALSE;
+ }
+
+ /* evaluate the buffer size and the number of buffers needed */
+ wfsink->free_buffers_count = wfsink->buffer_count;
+
+ /* allocate wave buffers */
+ wfsink->wave_buffers = (WAVEHDR *) g_new0 (WAVEHDR, wfsink->buffer_count);
+ if (!wfsink->wave_buffers) {
+ GST_ELEMENT_ERROR (wfsink, RESOURCE, OPEN_WRITE,
+ ("gst_waveform_sink_prepare: Failed to allocate wave buffer headers (buffer count=%d)",
+ wfsink->buffer_count), (NULL));
+ return FALSE;
+ }
+ memset (wfsink->wave_buffers, 0, sizeof (WAVEHDR) * wfsink->buffer_count);
+
+ /* setup headers */
+ for (index = 0; index < wfsink->buffer_count; index++) {
+ wfsink->wave_buffers[index].dwBufferLength = wfsink->buffer_size;
+ wfsink->wave_buffers[index].lpData = g_new0 (gchar, wfsink->buffer_size);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_waveform_sink_unprepare (GstAudioSink * asink)
+{
+ GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink);
+
+ /* free wave buffers */
+ if (wfsink->wave_buffers) {
+ guint index;
+
+ for (index = 0; index < wfsink->buffer_count; index++) {
+ if (wfsink->wave_buffers[index].dwFlags & WHDR_PREPARED) {
+ MMRESULT mmresult = waveOutUnprepareHeader (wfsink->hwaveout,
+ &wfsink->wave_buffers[index], sizeof (WAVEHDR));
+ if (mmresult != MMSYSERR_NOERROR) {
+ waveOutGetErrorText (mmresult, wfsink->error_string,
+ ERROR_LENGTH - 1);
+ GST_CAT_WARNING_OBJECT (waveformsink_debug, wfsink,
+ "gst_waveform_sink_unprepare: Error unpreparing buffer => %s",
+ wfsink->error_string);
+ }
+ }
+ g_free (wfsink->wave_buffers[index].lpData);
+ }
+ g_free (wfsink->wave_buffers);
+ wfsink->wave_buffers = NULL;
+ }
+
+ /* close waveform-audio output device */
+ if (wfsink->hwaveout) {
+ waveOutClose (wfsink->hwaveout);
+ wfsink->hwaveout = NULL;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_waveform_sink_close (GstAudioSink * asink)
+{
+ GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink);
+
+ return TRUE;
+}
+
+static guint
+gst_waveform_sink_write (GstAudioSink * asink, gpointer data, guint length)
+{
+ GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink);
+ WAVEHDR *waveheader;
+ MMRESULT mmresult;
+ guint bytes_to_write = length;
+ guint remaining_length = length;
+
+ wfsink->bytes_in_queue += length;
+
+ while (remaining_length > 0) {
+ if (wfsink->free_buffers_count == 0) {
+ /* no free buffer available, wait for one */
+ Sleep (10);
+ continue;
+ }
+
+ /* get the current write buffer header */
+ waveheader = &wfsink->wave_buffers[wfsink->write_buffer];
+
+ /* unprepare the header if needed */
+ if (waveheader->dwFlags & WHDR_PREPARED) {
+ mmresult =
+ waveOutUnprepareHeader (wfsink->hwaveout, waveheader,
+ sizeof (WAVEHDR));
+ if (mmresult != MMSYSERR_NOERROR) {
+ waveOutGetErrorText (mmresult, wfsink->error_string, ERROR_LENGTH - 1);
+ GST_CAT_WARNING_OBJECT (waveformsink_debug, wfsink,
+ "Error unpreparing buffer => %s", wfsink->error_string);
+ }
+ }
+
+ if (wfsink->buffer_size - waveheader->dwUser >= remaining_length)
+ bytes_to_write = remaining_length;
+ else
+ bytes_to_write = wfsink->buffer_size - waveheader->dwUser;
+
+ memcpy (waveheader->lpData + waveheader->dwUser, data, bytes_to_write);
+ waveheader->dwUser += bytes_to_write;
+ remaining_length -= bytes_to_write;
+ data = (guint8 *) data + bytes_to_write;
+
+ if (waveheader->dwUser == wfsink->buffer_size) {
+ /* we have filled a buffer, let's prepare it and next write it to the device */
+ mmresult =
+ waveOutPrepareHeader (wfsink->hwaveout, waveheader, sizeof (WAVEHDR));
+ if (mmresult != MMSYSERR_NOERROR) {
+ waveOutGetErrorText (mmresult, wfsink->error_string, ERROR_LENGTH - 1);
+ GST_CAT_WARNING_OBJECT (waveformsink_debug, wfsink,
+ "gst_waveform_sink_write: Error preparing header => %s",
+ wfsink->error_string);
+ }
+ mmresult = waveOutWrite (wfsink->hwaveout, waveheader, sizeof (WAVEHDR));
+ if (mmresult != MMSYSERR_NOERROR) {
+ waveOutGetErrorText (mmresult, wfsink->error_string, ERROR_LENGTH - 1);
+ GST_CAT_WARNING_OBJECT (waveformsink_debug, wfsink,
+ "gst_waveform_sink_write: Error writting buffer to the device => %s",
+ wfsink->error_string);
+ }
+
+ EnterCriticalSection (&wfsink->critic_wave);
+ wfsink->free_buffers_count--;
+ LeaveCriticalSection (&wfsink->critic_wave);
+
+ wfsink->write_buffer++;
+ wfsink->write_buffer %= wfsink->buffer_count;
+ waveheader->dwUser = 0;
+ wfsink->bytes_in_queue = 0;
+ GST_CAT_LOG_OBJECT (waveformsink_debug, wfsink,
+ "gst_waveform_sink_write: Writting a buffer to the device (free buffers remaining=%d, write buffer=%d)",
+ wfsink->free_buffers_count, wfsink->write_buffer);
+ }
+ }
+
+ return length;
+}
+
+static guint
+gst_waveform_sink_delay (GstAudioSink * asink)
+{
+ /* return the number of samples in queue (device+internal queue) */
+ GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink);
+ guint bytes_in_device =
+ (wfsink->buffer_count - wfsink->free_buffers_count) * wfsink->buffer_size;
+ guint delay =
+ (bytes_in_device + wfsink->bytes_in_queue) / wfsink->bytes_per_sample;
+ return delay;
+}
+
+static void
+gst_waveform_sink_reset (GstAudioSink * asink)
+{
+ GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink);
+ MMRESULT mmresult = waveOutReset (wfsink->hwaveout);
+
+ if (mmresult != MMSYSERR_NOERROR) {
+ waveOutGetErrorText (mmresult, wfsink->error_string, ERROR_LENGTH - 1);
+ GST_CAT_WARNING_OBJECT (waveformsink_debug, wfsink,
+ "gst_waveform_sink_reset: Error reseting waveform-audio device => %s",
+ wfsink->error_string);
+ }
+}
+
+GstCaps *
+gst_waveform_sink_create_caps (gint rate, gint channels, gint bits_per_sample)
+{
+ GstCaps *caps = NULL;
+
+ caps = gst_caps_new_simple ("audio/x-raw-int",
+ "width", G_TYPE_INT, bits_per_sample,
+ "depth", G_TYPE_INT, bits_per_sample,
+ "endianness", G_TYPE_INT, G_BYTE_ORDER,
+ "signed", G_TYPE_BOOLEAN, TRUE,
+ "channels", G_TYPE_INT, channels, "rate", G_TYPE_INT, rate, NULL);
+ return caps;
+}
+
+void CALLBACK
+waveOutProc (HWAVEOUT hwo,
+ UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
+{
+ GstWaveFormSink *wfsink = (GstWaveFormSink *) dwInstance;
+
+ if (uMsg == WOM_DONE) {
+ EnterCriticalSection (&wfsink->critic_wave);
+ wfsink->free_buffers_count++;
+ LeaveCriticalSection (&wfsink->critic_wave);
+ }
+}
diff --git a/sys/waveform/gstwaveformsink.h b/sys/waveform/gstwaveformsink.h
new file mode 100644
index 0000000..b23aea1
--- /dev/null
+++ b/sys/waveform/gstwaveformsink.h
@@ -0,0 +1,107 @@
+/* GStreamer
+ * Copyright (C) 2005 Sebastien Moutte <sebastien@moutte.net>
+ *
+ * gstwaveformsink.h:
+ *
+ * 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.
+ */
+
+#ifndef __GST_WAVEFORMSINK_H__
+#define __GST_WAVEFORMSINK_H__
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosink.h>
+
+#include <windows.h>
+#include <mmsystem.h>
+
+#ifndef WAVE_FORMAT_96M08
+#define WAVE_FORMAT_96M08 0x00001000 /* 96 kHz, Mono, 8-bit */
+#endif
+
+#ifndef WAVE_FORMAT_96S08
+#define WAVE_FORMAT_96S08 0x00002000 /* 96 kHz, Stereo, 8-bit */
+#endif
+
+#ifndef WAVE_FORMAT_96M16
+#define WAVE_FORMAT_96M16 0x00004000 /* 96 kHz, Mono, 16-bit */
+#endif
+
+#ifndef WAVE_FORMAT_96S16
+#define WAVE_FORMAT_96S16 0x00008000 /* 96 kHz, Stereo, 16-bit */
+#endif
+
+#define ERROR_LENGTH MAXERRORLENGTH+50
+#define BUFFER_COUNT 20
+#define BUFFER_SIZE 8192
+
+G_BEGIN_DECLS
+#define GST_TYPE_WAVEFORM_SINK (gst_waveform_sink_get_type())
+#define GST_WAVEFORM_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_WAVEFORM_SINK,GstWaveFormSink))
+#define GST_WAVEFORM_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_WAVEFORM_SINK,GstWaveFormSinkClass))
+#define GST_IS_WAVEFORM_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_WAVEFORM_SINK))
+#define GST_IS_WAVEFORM_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_WAVEFORM_SINK))
+typedef struct _GstWaveFormSink GstWaveFormSink;
+typedef struct _GstWaveFormSinkClass GstWaveFormSinkClass;
+
+struct _GstWaveFormSink
+{
+ /* parent object */
+ GstAudioSink sink;
+
+ /* supported caps */
+ GstCaps *cached_caps;
+
+ /* handle to the waveform-audio output device */
+ HWAVEOUT hwaveout;
+
+ /* table of buffer headers */
+ WAVEHDR *wave_buffers;
+
+ /* critical section protecting access to the number of free buffers */
+ CRITICAL_SECTION critic_wave;
+
+ /* number of free buffers available */
+ guint free_buffers_count;
+
+ /* current free buffer where you have to write incoming data */
+ guint write_buffer;
+
+ /* size of buffers streamed to the device */
+ guint buffer_size;
+
+ /* number of buffers streamed to the device */
+ guint buffer_count;
+
+ /* total of bytes in queue before they are written to the device */
+ guint bytes_in_queue;
+
+ /* bytes per sample from setcaps used to evaluate the number samples returned by delay */
+ guint bytes_per_sample;
+
+ /* wave form error string */
+ gchar error_string[ERROR_LENGTH];
+};
+
+struct _GstWaveFormSinkClass
+{
+ GstAudioSinkClass parent_class;
+};
+
+GType gst_waveform_sink_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_WAVEFORMSINK_H__ */
diff --git a/sys/ximage/Makefile.am b/sys/ximage/Makefile.am
new file mode 100644
index 0000000..db3ab22
--- /dev/null
+++ b/sys/ximage/Makefile.am
@@ -0,0 +1,16 @@
+plugin_LTLIBRARIES = libgstximagesrc.la
+
+libgstximagesrc_la_SOURCES = gstximagesrc.c ximageutil.c
+libgstximagesrc_la_CFLAGS = \
+ $(GST_PLUGINS_BASE_CFLAGS) \
+ $(GST_BASE_CFLAGS) \
+ $(GST_CFLAGS) \
+ $(X_CFLAGS) $(XFIXES_CFLAGS) $(XDAMAGE_CFLAGS)
+libgstximagesrc_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) \
+ $(GST_BASE_LIBS) \
+ $(X_LIBS) $(XSHM_LIBS) $(XFIXES_LIBS) $(XDAMAGE_LIBS)
+libgstximagesrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstximagesrc_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = gstximagesrc.h ximageutil.h
diff --git a/sys/ximage/Makefile.in b/sys/ximage/Makefile.in
new file mode 100644
index 0000000..129f9a8
--- /dev/null
+++ b/sys/ximage/Makefile.in
@@ -0,0 +1,825 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sys/ximage
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
+ $(top_srcdir)/common/m4/as-auto-alt.m4 \
+ $(top_srcdir)/common/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/common/m4/as-gcc-inline-assembly.m4 \
+ $(top_srcdir)/common/m4/as-objc.m4 \
+ $(top_srcdir)/common/m4/as-python.m4 \
+ $(top_srcdir)/common/m4/as-scrub-include.m4 \
+ $(top_srcdir)/common/m4/as-version.m4 \
+ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
+ $(top_srcdir)/common/m4/gst-arch.m4 \
+ $(top_srcdir)/common/m4/gst-args.m4 \
+ $(top_srcdir)/common/m4/gst-check.m4 \
+ $(top_srcdir)/common/m4/gst-default.m4 \
+ $(top_srcdir)/common/m4/gst-dowhile.m4 \
+ $(top_srcdir)/common/m4/gst-error.m4 \
+ $(top_srcdir)/common/m4/gst-feature.m4 \
+ $(top_srcdir)/common/m4/gst-gettext.m4 \
+ $(top_srcdir)/common/m4/gst-glib2.m4 \
+ $(top_srcdir)/common/m4/gst-package-release-datetime.m4 \
+ $(top_srcdir)/common/m4/gst-platform.m4 \
+ $(top_srcdir)/common/m4/gst-plugin-docs.m4 \
+ $(top_srcdir)/common/m4/gst-plugindir.m4 \
+ $(top_srcdir)/common/m4/gst-x11.m4 \
+ $(top_srcdir)/common/m4/gst.m4 \
+ $(top_srcdir)/common/m4/gtk-doc.m4 \
+ $(top_srcdir)/common/m4/orc.m4 $(top_srcdir)/common/m4/pkg.m4 \
+ $(top_srcdir)/m4/aalib.m4 $(top_srcdir)/m4/esd.m4 \
+ $(top_srcdir)/m4/gconf-2.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gst-fionread.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgstximagesrc_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_libgstximagesrc_la_OBJECTS = libgstximagesrc_la-gstximagesrc.lo \
+ libgstximagesrc_la-ximageutil.lo
+libgstximagesrc_la_OBJECTS = $(am_libgstximagesrc_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libgstximagesrc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(libgstximagesrc_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
+ $(CCLD) $(libgstximagesrc_la_CFLAGS) $(CFLAGS) \
+ $(libgstximagesrc_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libgstximagesrc_la_SOURCES)
+DIST_SOURCES = $(libgstximagesrc_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+AALIB_CFLAGS = @AALIB_CFLAGS@
+AALIB_CONFIG = @AALIB_CONFIG@
+AALIB_LIBS = @AALIB_LIBS@
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+ANNODEX_CFLAGS = @ANNODEX_CFLAGS@
+ANNODEX_LIBS = @ANNODEX_LIBS@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BZ2_LIBS = @BZ2_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_GOBJECT_CFLAGS = @CAIRO_GOBJECT_CFLAGS@
+CAIRO_GOBJECT_LIBS = @CAIRO_GOBJECT_LIBS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_AUDIOSINK = @DEFAULT_AUDIOSINK@
+DEFAULT_AUDIOSRC = @DEFAULT_AUDIOSRC@
+DEFAULT_VIDEOSINK = @DEFAULT_VIDEOSINK@
+DEFAULT_VIDEOSRC = @DEFAULT_VIDEOSRC@
+DEFAULT_VISUALIZER = @DEFAULT_VISUALIZER@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DEPRECATED_CFLAGS = @DEPRECATED_CFLAGS@
+DIRECTSOUND_CFLAGS = @DIRECTSOUND_CFLAGS@
+DIRECTSOUND_LDFLAGS = @DIRECTSOUND_LDFLAGS@
+DIRECTSOUND_LIBS = @DIRECTSOUND_LIBS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DV1394_CFLAGS = @DV1394_CFLAGS@
+DV1394_LIBS = @DV1394_LIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ERROR_CFLAGS = @ERROR_CFLAGS@
+ERROR_CXXFLAGS = @ERROR_CXXFLAGS@
+ESD_CFLAGS = @ESD_CFLAGS@
+ESD_CONFIG = @ESD_CONFIG@
+ESD_LIBS = @ESD_LIBS@
+EXEEXT = @EXEEXT@
+FFLAGS = @FFLAGS@
+FGREP = @FGREP@
+FLAC_CFLAGS = @FLAC_CFLAGS@
+FLAC_LIBS = @FLAC_LIBS@
+GCONFTOOL = @GCONFTOOL@
+GCONF_CFLAGS = @GCONF_CFLAGS@
+GCONF_LIBS = @GCONF_LIBS@
+GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+GCOV = @GCOV@
+GCOV_CFLAGS = @GCOV_CFLAGS@
+GCOV_LIBS = @GCOV_LIBS@
+GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@
+GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_EXTRA_CFLAGS = @GLIB_EXTRA_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_PREFIX = @GLIB_PREFIX@
+GLIB_REQ = @GLIB_REQ@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+GSTPB_PLUGINS_DIR = @GSTPB_PLUGINS_DIR@
+GSTPB_PREFIX = @GSTPB_PREFIX@
+GST_ALL_LDFLAGS = @GST_ALL_LDFLAGS@
+GST_BASE_CFLAGS = @GST_BASE_CFLAGS@
+GST_BASE_LIBS = @GST_BASE_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_CONTROLLER_CFLAGS = @GST_CONTROLLER_CFLAGS@
+GST_CONTROLLER_LIBS = @GST_CONTROLLER_LIBS@
+GST_CXXFLAGS = @GST_CXXFLAGS@
+GST_GDP_CFLAGS = @GST_GDP_CFLAGS@
+GST_GDP_LIBS = @GST_GDP_LIBS@
+GST_LEVEL_DEFAULT = @GST_LEVEL_DEFAULT@
+GST_LIBS = @GST_LIBS@
+GST_LICENSE = @GST_LICENSE@
+GST_LT_LDFLAGS = @GST_LT_LDFLAGS@
+GST_MAJORMINOR = @GST_MAJORMINOR@
+GST_OPTION_CFLAGS = @GST_OPTION_CFLAGS@
+GST_OPTION_CXXFLAGS = @GST_OPTION_CXXFLAGS@
+GST_PACKAGE_NAME = @GST_PACKAGE_NAME@
+GST_PACKAGE_ORIGIN = @GST_PACKAGE_ORIGIN@
+GST_PLUGINS_ALL = @GST_PLUGINS_ALL@
+GST_PLUGINS_BASE_CFLAGS = @GST_PLUGINS_BASE_CFLAGS@
+GST_PLUGINS_BASE_DIR = @GST_PLUGINS_BASE_DIR@
+GST_PLUGINS_BASE_LIBS = @GST_PLUGINS_BASE_LIBS@
+GST_PLUGINS_DIR = @GST_PLUGINS_DIR@
+GST_PLUGINS_SELECTED = @GST_PLUGINS_SELECTED@
+GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@
+GST_PREFIX = @GST_PREFIX@
+GST_TOOLS_DIR = @GST_TOOLS_DIR@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_X11_CFLAGS = @GTK_X11_CFLAGS@
+GTK_X11_LIBS = @GTK_X11_LIBS@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+HAVE_AVC1394 = @HAVE_AVC1394@
+HAVE_BZ2 = @HAVE_BZ2@
+HAVE_CXX = @HAVE_CXX@
+HAVE_DIRECTSOUND = @HAVE_DIRECTSOUND@
+HAVE_GCONFTOOL = @HAVE_GCONFTOOL@
+HAVE_ROM1394 = @HAVE_ROM1394@
+HAVE_SPEEX = @HAVE_SPEEX@
+HAVE_X = @HAVE_X@
+HAVE_XSHM = @HAVE_XSHM@
+HAVE_ZLIB = @HAVE_ZLIB@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JACK_0_120_1_CFLAGS = @JACK_0_120_1_CFLAGS@
+JACK_0_120_1_LIBS = @JACK_0_120_1_LIBS@
+JACK_1_9_7_CFLAGS = @JACK_1_9_7_CFLAGS@
+JACK_1_9_7_LIBS = @JACK_1_9_7_LIBS@
+JACK_CFLAGS = @JACK_CFLAGS@
+JACK_LIBS = @JACK_LIBS@
+JPEG_LIBS = @JPEG_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCACA_CFLAGS = @LIBCACA_CFLAGS@
+LIBCACA_LIBS = @LIBCACA_LIBS@
+LIBDV_CFLAGS = @LIBDV_CFLAGS@
+LIBDV_LIBS = @LIBDV_LIBS@
+LIBICONV = @LIBICONV@
+LIBIEC61883_CFLAGS = @LIBIEC61883_CFLAGS@
+LIBIEC61883_LIBS = @LIBIEC61883_LIBS@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBPNG_CFLAGS = @LIBPNG_CFLAGS@
+LIBPNG_LIBS = @LIBPNG_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBV4L2_CFLAGS = @LIBV4L2_CFLAGS@
+LIBV4L2_LIBS = @LIBV4L2_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCALEDIR = @LOCALEDIR@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJC_LDFLAGS = @OBJC_LDFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORCC = @ORCC@
+ORCC_FLAGS = @ORCC_FLAGS@
+ORC_CFLAGS = @ORC_CFLAGS@
+ORC_LIBS = @ORC_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MICRO = @PACKAGE_VERSION_MICRO@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_NANO = @PACKAGE_VERSION_NANO@
+PACKAGE_VERSION_RELEASE = @PACKAGE_VERSION_RELEASE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PLUGINDIR = @PLUGINDIR@
+POSUB = @POSUB@
+PROFILE_CFLAGS = @PROFILE_CFLAGS@
+PULSE_0_9_20_CFLAGS = @PULSE_0_9_20_CFLAGS@
+PULSE_0_9_20_LIBS = @PULSE_0_9_20_LIBS@
+PULSE_1_0_CFLAGS = @PULSE_1_0_CFLAGS@
+PULSE_1_0_LIBS = @PULSE_1_0_LIBS@
+PULSE_CFLAGS = @PULSE_CFLAGS@
+PULSE_LIBS = @PULSE_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RAW1394_CFLAGS = @RAW1394_CFLAGS@
+RAW1394_LIBS = @RAW1394_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHOUT2_CFLAGS = @SHOUT2_CFLAGS@
+SHOUT2_LIBS = @SHOUT2_LIBS@
+SOUP_CFLAGS = @SOUP_CFLAGS@
+SOUP_LIBS = @SOUP_LIBS@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+TAGLIB_CFLAGS = @TAGLIB_CFLAGS@
+TAGLIB_CXXFLAGS = @TAGLIB_CXXFLAGS@
+TAGLIB_LIBS = @TAGLIB_LIBS@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VALGRIND_PATH = @VALGRIND_PATH@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+WAVPACK_CFLAGS = @WAVPACK_CFLAGS@
+WAVPACK_LIBS = @WAVPACK_LIBS@
+WIN32_LIBS = @WIN32_LIBS@
+XDAMAGE_CFLAGS = @XDAMAGE_CFLAGS@
+XDAMAGE_LIBS = @XDAMAGE_LIBS@
+XFIXES_CFLAGS = @XFIXES_CFLAGS@
+XFIXES_LIBS = @XFIXES_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+XMKMF = @XMKMF@
+XSHM_LIBS = @XSHM_LIBS@
+XVIDEO_LIBS = @XVIDEO_LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+plugin_LTLIBRARIES = libgstximagesrc.la
+libgstximagesrc_la_SOURCES = gstximagesrc.c ximageutil.c
+libgstximagesrc_la_CFLAGS = \
+ $(GST_PLUGINS_BASE_CFLAGS) \
+ $(GST_BASE_CFLAGS) \
+ $(GST_CFLAGS) \
+ $(X_CFLAGS) $(XFIXES_CFLAGS) $(XDAMAGE_CFLAGS)
+
+libgstximagesrc_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) \
+ $(GST_BASE_LIBS) \
+ $(X_LIBS) $(XSHM_LIBS) $(XFIXES_LIBS) $(XDAMAGE_LIBS)
+
+libgstximagesrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstximagesrc_la_LIBTOOLFLAGS = --tag=disable-static
+noinst_HEADERS = gstximagesrc.h ximageutil.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sys/ximage/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu sys/ximage/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgstximagesrc.la: $(libgstximagesrc_la_OBJECTS) $(libgstximagesrc_la_DEPENDENCIES) $(EXTRA_libgstximagesrc_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgstximagesrc_la_LINK) -rpath $(plugindir) $(libgstximagesrc_la_OBJECTS) $(libgstximagesrc_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstximagesrc_la-gstximagesrc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstximagesrc_la-ximageutil.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libgstximagesrc_la-gstximagesrc.lo: gstximagesrc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstximagesrc_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstximagesrc_la_CFLAGS) $(CFLAGS) -MT libgstximagesrc_la-gstximagesrc.lo -MD -MP -MF $(DEPDIR)/libgstximagesrc_la-gstximagesrc.Tpo -c -o libgstximagesrc_la-gstximagesrc.lo `test -f 'gstximagesrc.c' || echo '$(srcdir)/'`gstximagesrc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstximagesrc_la-gstximagesrc.Tpo $(DEPDIR)/libgstximagesrc_la-gstximagesrc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstximagesrc.c' object='libgstximagesrc_la-gstximagesrc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstximagesrc_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstximagesrc_la_CFLAGS) $(CFLAGS) -c -o libgstximagesrc_la-gstximagesrc.lo `test -f 'gstximagesrc.c' || echo '$(srcdir)/'`gstximagesrc.c
+
+libgstximagesrc_la-ximageutil.lo: ximageutil.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstximagesrc_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstximagesrc_la_CFLAGS) $(CFLAGS) -MT libgstximagesrc_la-ximageutil.lo -MD -MP -MF $(DEPDIR)/libgstximagesrc_la-ximageutil.Tpo -c -o libgstximagesrc_la-ximageutil.lo `test -f 'ximageutil.c' || echo '$(srcdir)/'`ximageutil.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstximagesrc_la-ximageutil.Tpo $(DEPDIR)/libgstximagesrc_la-ximageutil.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ximageutil.c' object='libgstximagesrc_la-ximageutil.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstximagesrc_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstximagesrc_la_CFLAGS) $(CFLAGS) -c -o libgstximagesrc_la-ximageutil.lo `test -f 'ximageutil.c' || echo '$(srcdir)/'`ximageutil.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sys/ximage/gstximagesrc.c b/sys/ximage/gstximagesrc.c
new file mode 100644
index 0000000..36c0b44
--- /dev/null
+++ b/sys/ximage/gstximagesrc.c
@@ -0,0 +1,1317 @@
+/* GStreamer
+ *
+ * Copyright (C) 2006 Zaheer Merali <zaheerabbas at merali dot org>
+ *
+ * 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-ximagesrc
+ *
+ * This element captures your X Display and creates raw RGB video. It uses
+ * the XDamage extension if available to only capture areas of the screen that
+ * have changed since the last frame. It uses the XFixes extension if
+ * available to also capture your mouse pointer. By default it will fixate to
+ * 25 frames per second.
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * |[
+ * gst-launch ximagesrc ! video/x-raw-rgb,framerate=5/1 ! ffmpegcolorspace ! theoraenc ! oggmux ! filesink location=desktop.ogg
+ * ]| Encodes your X display to an Ogg theora video at 5 frames per second.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "gstximagesrc.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <gst/gst.h>
+#include <gst/gst-i18n-plugin.h>
+
+#include "gst/glib-compat-private.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_debug_ximage_src);
+#define GST_CAT_DEFAULT gst_debug_ximage_src
+
+static GstStaticPadTemplate t =
+GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-raw-rgb, "
+ "framerate = (fraction) [ 0, MAX ], "
+ "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ], "
+ "pixel-aspect-ratio = (fraction) [ 0, MAX ]"));
+
+enum
+{
+ PROP_0,
+ PROP_DISPLAY_NAME,
+ PROP_SCREEN_NUM,
+ PROP_SHOW_POINTER,
+ PROP_USE_DAMAGE,
+ PROP_STARTX,
+ PROP_STARTY,
+ PROP_ENDX,
+ PROP_ENDY,
+ PROP_REMOTE,
+ PROP_XID,
+ PROP_XNAME,
+};
+
+GST_BOILERPLATE (GstXImageSrc, gst_ximage_src, GstPushSrc, GST_TYPE_PUSH_SRC);
+
+static void gst_ximage_src_fixate (GstPad * pad, GstCaps * caps);
+static void gst_ximage_src_clear_bufpool (GstXImageSrc * ximagesrc);
+
+/* Called when a buffer is returned from the pipeline */
+static void
+gst_ximage_src_return_buf (GstXImageSrc * ximagesrc,
+ GstXImageSrcBuffer * ximage)
+{
+ /* If our geometry changed we can't reuse that image. */
+ if ((ximage->width != ximagesrc->width) ||
+ (ximage->height != ximagesrc->height)) {
+ GST_DEBUG_OBJECT (ximagesrc,
+ "destroy image %p as its size changed %dx%d vs current %dx%d",
+ ximage, ximage->width, ximage->height,
+ ximagesrc->width, ximagesrc->height);
+ g_mutex_lock (ximagesrc->x_lock);
+ gst_ximageutil_ximage_destroy (ximagesrc->xcontext, ximage);
+ g_mutex_unlock (ximagesrc->x_lock);
+ } else {
+ /* In that case we can reuse the image and add it to our image pool. */
+ GST_LOG_OBJECT (ximagesrc, "recycling image %p in pool", ximage);
+ /* need to increment the refcount again to recycle */
+ gst_buffer_ref (GST_BUFFER (ximage));
+ g_mutex_lock (ximagesrc->pool_lock);
+ GST_BUFFER_FLAGS (GST_BUFFER (ximage)) = 0; /* clear out any flags from the previous use */
+ ximagesrc->buffer_pool = g_slist_prepend (ximagesrc->buffer_pool, ximage);
+ g_mutex_unlock (ximagesrc->pool_lock);
+ }
+}
+
+static Window
+gst_ximage_src_find_window (GstXImageSrc * src, Window root, const char *name)
+{
+ Window *children;
+ Window window = 0, root_return, parent_return;
+ unsigned int nchildren;
+ char *tmpname;
+ int n, status;
+
+ status = XFetchName (src->xcontext->disp, root, &tmpname);
+ if (status && !strcmp (name, tmpname))
+ return root;
+
+ status =
+ XQueryTree (src->xcontext->disp, root, &root_return, &parent_return,
+ &children, &nchildren);
+ if (!status || !children)
+ return (Window) 0;
+
+ for (n = 0; n < nchildren; ++n) {
+ window = gst_ximage_src_find_window (src, children[n], name);
+ if (window != 0)
+ break;
+ }
+
+ XFree (children);
+ return window;
+}
+
+static gboolean
+gst_ximage_src_open_display (GstXImageSrc * s, const gchar * name)
+{
+ g_return_val_if_fail (GST_IS_XIMAGE_SRC (s), FALSE);
+
+ if (s->xcontext != NULL)
+ return TRUE;
+
+ g_mutex_lock (s->x_lock);
+ s->xcontext = ximageutil_xcontext_get (GST_ELEMENT (s), name);
+ if (s->xcontext == NULL) {
+ g_mutex_unlock (s->x_lock);
+ GST_ELEMENT_ERROR (s, RESOURCE, OPEN_READ,
+ ("Could not open X display for reading"),
+ ("NULL returned from getting xcontext"));
+ return FALSE;
+ }
+ s->width = s->xcontext->width;
+ s->height = s->xcontext->height;
+
+ s->xwindow = s->xcontext->root;
+ if (s->xid != 0 || s->xname) {
+ int status;
+ XWindowAttributes attrs;
+ Window window;
+
+ if (s->xid != 0) {
+ status = XGetWindowAttributes (s->xcontext->disp, s->xid, &attrs);
+ if (status) {
+ GST_DEBUG_OBJECT (s, "Found window XID %" G_GUINT64_FORMAT, s->xid);
+ s->xwindow = s->xid;
+ goto window_found;
+ } else {
+ GST_WARNING_OBJECT (s, "Failed to get window %" G_GUINT64_FORMAT
+ " attributes", s->xid);
+ }
+ }
+
+ if (s->xname) {
+ GST_DEBUG_OBJECT (s, "Looking for window %s", s->xname);
+ window = gst_ximage_src_find_window (s, s->xcontext->root, s->xname);
+ if (window != 0) {
+ GST_DEBUG_OBJECT (s, "Found window named %s, ", s->xname);
+ status = XGetWindowAttributes (s->xcontext->disp, window, &attrs);
+ if (status) {
+ s->xwindow = window;
+ goto window_found;
+ } else {
+ GST_WARNING_OBJECT (s, "Failed to get window attributes for "
+ "window named %s", s->xname);
+ }
+ }
+ }
+
+ GST_INFO_OBJECT (s, "Using root window");
+ goto use_root_window;
+
+ window_found:
+ g_assert (s->xwindow != 0);
+ s->width = attrs.width;
+ s->height = attrs.height;
+ GST_INFO_OBJECT (s, "Using default window size of %dx%d",
+ s->width, s->height);
+ }
+use_root_window:
+
+#ifdef HAVE_XFIXES
+ /* check if xfixes supported */
+ {
+ int error_base;
+
+ if (XFixesQueryExtension (s->xcontext->disp, &s->fixes_event_base,
+ &error_base)) {
+ s->have_xfixes = TRUE;
+ GST_DEBUG_OBJECT (s, "X Server supports XFixes");
+ } else {
+
+ GST_DEBUG_OBJECT (s, "X Server does not support XFixes");
+ }
+ }
+
+#ifdef HAVE_XDAMAGE
+ /* check if xdamage is supported */
+ {
+ int error_base;
+ long evmask = NoEventMask;
+
+ s->have_xdamage = FALSE;
+ s->damage = None;
+ s->damage_copy_gc = None;
+ s->damage_region = None;
+
+ if (XDamageQueryExtension (s->xcontext->disp, &s->damage_event_base,
+ &error_base)) {
+ s->damage =
+ XDamageCreate (s->xcontext->disp, s->xwindow, XDamageReportNonEmpty);
+ if (s->damage != None) {
+ s->damage_region = XFixesCreateRegion (s->xcontext->disp, NULL, 0);
+ if (s->damage_region != None) {
+ XGCValues values;
+
+ GST_DEBUG_OBJECT (s, "Using XDamage extension");
+ values.subwindow_mode = IncludeInferiors;
+ s->damage_copy_gc = XCreateGC (s->xcontext->disp,
+ s->xwindow, GCSubwindowMode, &values);
+ XSelectInput (s->xcontext->disp, s->xwindow, evmask);
+
+ s->have_xdamage = TRUE;
+ } else {
+ XDamageDestroy (s->xcontext->disp, s->damage);
+ s->damage = None;
+ }
+ } else
+ GST_DEBUG_OBJECT (s, "Could not attach to XDamage");
+ } else {
+ GST_DEBUG_OBJECT (s, "X Server does not have XDamage extension");
+ }
+ }
+#endif
+#endif
+
+ g_mutex_unlock (s->x_lock);
+
+ if (s->xcontext == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_ximage_src_start (GstBaseSrc * basesrc)
+{
+ GstXImageSrc *s = GST_XIMAGE_SRC (basesrc);
+
+ s->last_frame_no = -1;
+#ifdef HAVE_XDAMAGE
+ if (s->last_ximage)
+ gst_buffer_unref (GST_BUFFER_CAST (s->last_ximage));
+ s->last_ximage = NULL;
+#endif
+ return gst_ximage_src_open_display (s, s->display_name);
+}
+
+static gboolean
+gst_ximage_src_stop (GstBaseSrc * basesrc)
+{
+ GstXImageSrc *src = GST_XIMAGE_SRC (basesrc);
+
+#ifdef HAVE_XDAMAGE
+ if (src->last_ximage)
+ gst_buffer_unref (GST_BUFFER_CAST (src->last_ximage));
+ src->last_ximage = NULL;
+#endif
+
+ gst_ximage_src_clear_bufpool (src);
+
+#ifdef HAVE_XFIXES
+ if (src->cursor_image)
+ XFree (src->cursor_image);
+ src->cursor_image = NULL;
+#endif
+
+ if (src->xcontext) {
+ g_mutex_lock (src->x_lock);
+
+#ifdef HAVE_XDAMAGE
+ if (src->damage_copy_gc != None) {
+ XFreeGC (src->xcontext->disp, src->damage_copy_gc);
+ src->damage_copy_gc = None;
+ }
+ if (src->damage_region != None) {
+ XFixesDestroyRegion (src->xcontext->disp, src->damage_region);
+ src->damage_region = None;
+ }
+ if (src->damage != None) {
+ XDamageDestroy (src->xcontext->disp, src->damage);
+ src->damage = None;
+ }
+#endif
+
+ ximageutil_xcontext_clear (src->xcontext);
+ src->xcontext = NULL;
+ g_mutex_unlock (src->x_lock);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_ximage_src_unlock (GstBaseSrc * basesrc)
+{
+ GstXImageSrc *src = GST_XIMAGE_SRC (basesrc);
+
+ /* Awaken the create() func if it's waiting on the clock */
+ GST_OBJECT_LOCK (src);
+ if (src->clock_id) {
+ GST_DEBUG_OBJECT (src, "Waking up waiting clock");
+ gst_clock_id_unschedule (src->clock_id);
+ }
+ GST_OBJECT_UNLOCK (src);
+
+ return TRUE;
+}
+
+static gboolean
+gst_ximage_src_recalc (GstXImageSrc * src)
+{
+ if (!src->xcontext)
+ return FALSE;
+
+ /* Maybe later we can check the display hasn't changed size */
+ /* We could use XQueryPointer to get only the current window. */
+ return TRUE;
+}
+
+#ifdef HAVE_XFIXES
+static void
+composite_pixel (GstXContext * xcontext, guchar * dest, guchar * src)
+{
+ guint8 r = src[2];
+ guint8 g = src[1];
+ guint8 b = src[0];
+ guint8 a = src[3];
+ guint8 dr, dg, db;
+ guint32 color;
+ gint r_shift, r_max, r_shift_out;
+ gint g_shift, g_max, g_shift_out;
+ gint b_shift, b_max, b_shift_out;
+
+ switch (xcontext->bpp) {
+ case 8:
+ color = *dest;
+ break;
+ case 16:
+ color = GUINT16_FROM_LE (*(guint16 *) (dest));
+ break;
+ case 32:
+ color = GUINT32_FROM_LE (*(guint32 *) (dest));
+ break;
+ default:
+ /* Should not reach here */
+ g_return_if_reached ();
+ }
+
+ /* possible optimisation:
+ * move the code that finds shift and max in the _link function */
+ for (r_shift = 0; !(xcontext->visual->red_mask & (1 << r_shift)); r_shift++);
+ for (g_shift = 0; !(xcontext->visual->green_mask & (1 << g_shift));
+ g_shift++);
+ for (b_shift = 0; !(xcontext->visual->blue_mask & (1 << b_shift)); b_shift++);
+
+ for (r_shift_out = 0; !(xcontext->visual->red_mask & (1 << r_shift_out));
+ r_shift_out++);
+ for (g_shift_out = 0; !(xcontext->visual->green_mask & (1 << g_shift_out));
+ g_shift_out++);
+ for (b_shift_out = 0; !(xcontext->visual->blue_mask & (1 << b_shift_out));
+ b_shift_out++);
+
+
+ r_max = (xcontext->visual->red_mask >> r_shift);
+ b_max = (xcontext->visual->blue_mask >> b_shift);
+ g_max = (xcontext->visual->green_mask >> g_shift);
+
+#define RGBXXX_R(x) (((x)>>r_shift) & (r_max))
+#define RGBXXX_G(x) (((x)>>g_shift) & (g_max))
+#define RGBXXX_B(x) (((x)>>b_shift) & (b_max))
+
+ dr = (RGBXXX_R (color) * 255) / r_max;
+ dg = (RGBXXX_G (color) * 255) / g_max;
+ db = (RGBXXX_B (color) * 255) / b_max;
+
+ dr = (r * a + (0xff - a) * dr) / 0xff;
+ dg = (g * a + (0xff - a) * dg) / 0xff;
+ db = (b * a + (0xff - a) * db) / 0xff;
+
+ color = (((dr * r_max) / 255) << r_shift_out) +
+ (((dg * g_max) / 255) << g_shift_out) +
+ (((db * b_max) / 255) << b_shift_out);
+
+ switch (xcontext->bpp) {
+ case 8:
+ *dest = color;
+ break;
+ case 16:
+ *(guint16 *) (dest) = color;
+ break;
+ case 32:
+ *(guint32 *) (dest) = color;
+ break;
+ default:
+ g_warning ("bpp %d not supported\n", xcontext->bpp);
+ }
+}
+#endif
+
+/* Retrieve an XImageSrcBuffer, preferably from our
+ * pool of existing images and populate it from the window */
+static GstXImageSrcBuffer *
+gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
+{
+ GstXImageSrcBuffer *ximage = NULL;
+
+ g_mutex_lock (ximagesrc->pool_lock);
+ while (ximagesrc->buffer_pool != NULL) {
+ ximage = ximagesrc->buffer_pool->data;
+
+ if ((ximage->width != ximagesrc->width) ||
+ (ximage->height != ximagesrc->height)) {
+ gst_ximage_buffer_free (ximage);
+ }
+
+ ximagesrc->buffer_pool = g_slist_delete_link (ximagesrc->buffer_pool,
+ ximagesrc->buffer_pool);
+ }
+ g_mutex_unlock (ximagesrc->pool_lock);
+
+ if (ximage == NULL) {
+ GstXContext *xcontext;
+ GstCaps *caps = NULL;
+
+ GST_DEBUG_OBJECT (ximagesrc, "creating image (%dx%d)",
+ ximagesrc->width, ximagesrc->height);
+
+ g_mutex_lock (ximagesrc->x_lock);
+ ximage = gst_ximageutil_ximage_new (ximagesrc->xcontext,
+ GST_ELEMENT (ximagesrc), ximagesrc->width, ximagesrc->height,
+ (BufferReturnFunc) (gst_ximage_src_return_buf));
+ if (ximage == NULL) {
+ GST_ELEMENT_ERROR (ximagesrc, RESOURCE, WRITE, (NULL),
+ ("could not create a %dx%d ximage", ximagesrc->width,
+ ximagesrc->height));
+ g_mutex_unlock (ximagesrc->x_lock);
+ return NULL;
+ }
+
+ xcontext = ximagesrc->xcontext;
+
+
+ caps = gst_caps_new_simple ("video/x-raw-rgb",
+ "bpp", G_TYPE_INT, xcontext->bpp,
+ "depth", G_TYPE_INT, xcontext->depth,
+ "endianness", G_TYPE_INT, xcontext->endianness,
+ "red_mask", G_TYPE_INT, xcontext->r_mask_output,
+ "green_mask", G_TYPE_INT, xcontext->g_mask_output,
+ "blue_mask", G_TYPE_INT, xcontext->b_mask_output,
+ "width", G_TYPE_INT, ximagesrc->width,
+ "height", G_TYPE_INT, ximagesrc->height,
+ "framerate", GST_TYPE_FRACTION, ximagesrc->fps_n, ximagesrc->fps_d,
+ "pixel-aspect-ratio", GST_TYPE_FRACTION,
+ gst_value_get_fraction_numerator (xcontext->par),
+ gst_value_get_fraction_denominator (xcontext->par), NULL);
+
+ gst_buffer_set_caps (GST_BUFFER (ximage), caps);
+ g_mutex_unlock (ximagesrc->x_lock);
+
+ gst_caps_unref (caps);
+ }
+
+ g_return_val_if_fail (GST_IS_XIMAGE_SRC (ximagesrc), NULL);
+#ifdef HAVE_XDAMAGE
+ if (ximagesrc->have_xdamage && ximagesrc->use_damage &&
+ ximagesrc->last_ximage != NULL) {
+ XEvent ev;
+
+ /* have_frame is TRUE when either the entire screen has been
+ * grabbed or when the last image has been copied */
+ gboolean have_frame = FALSE;
+
+ GST_DEBUG_OBJECT (ximagesrc, "Retrieving screen using XDamage");
+
+ do {
+ XNextEvent (ximagesrc->xcontext->disp, &ev);
+
+ if (ev.type == ximagesrc->damage_event_base + XDamageNotify) {
+ XserverRegion parts;
+ XRectangle *rects;
+ int nrects;
+
+ parts = XFixesCreateRegion (ximagesrc->xcontext->disp, 0, 0);
+ XDamageSubtract (ximagesrc->xcontext->disp, ximagesrc->damage, None,
+ parts);
+ /* Now copy out all of the damaged rectangles. */
+ rects = XFixesFetchRegion (ximagesrc->xcontext->disp, parts, &nrects);
+ if (rects != NULL) {
+ int i;
+
+ if (!have_frame) {
+ GST_LOG_OBJECT (ximagesrc,
+ "Copying from last frame ximage->size: %d",
+ GST_BUFFER_SIZE (GST_BUFFER (ximage)));
+ memcpy (GST_BUFFER_DATA (GST_BUFFER (ximage)),
+ GST_BUFFER_DATA (GST_BUFFER (ximagesrc->last_ximage)),
+ GST_BUFFER_SIZE (GST_BUFFER (ximage)));
+ have_frame = TRUE;
+ }
+ for (i = 0; i < nrects; i++) {
+ GST_LOG_OBJECT (ximagesrc,
+ "Damaged sub-region @ %d,%d size %dx%d reported",
+ rects[i].x, rects[i].y, rects[i].width, rects[i].height);
+
+ /* if we only want a small area, clip this damage region to
+ * area we want */
+ if (ximagesrc->endx > ximagesrc->startx &&
+ ximagesrc->endy > ximagesrc->starty) {
+ /* see if damage area intersects */
+ if (rects[i].x + rects[i].width - 1 < ximagesrc->startx ||
+ rects[i].x > ximagesrc->endx) {
+ /* trivial reject */
+ } else if (rects[i].y + rects[i].height - 1 < ximagesrc->starty ||
+ rects[i].y > ximagesrc->endy) {
+ /* trivial reject */
+ } else {
+ /* find intersect region */
+ int startx, starty, width, height;
+
+ startx = (rects[i].x < ximagesrc->startx) ? ximagesrc->startx :
+ rects[i].x;
+ starty = (rects[i].y < ximagesrc->starty) ? ximagesrc->starty :
+ rects[i].y;
+ width = (rects[i].x + rects[i].width - 1 < ximagesrc->endx) ?
+ rects[i].x + rects[i].width - startx :
+ ximagesrc->endx - startx + 1;
+ height = (rects[i].y + rects[i].height - 1 < ximagesrc->endy) ?
+ rects[i].y + rects[i].height - starty : ximagesrc->endy -
+ starty + 1;
+
+ GST_LOG_OBJECT (ximagesrc,
+ "Retrieving damaged sub-region @ %d,%d size %dx%d as intersect region",
+ startx, starty, width, height);
+ XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
+ startx, starty, width, height, AllPlanes, ZPixmap,
+ ximage->ximage, startx - ximagesrc->startx,
+ starty - ximagesrc->starty);
+ }
+ } else {
+
+ GST_LOG_OBJECT (ximagesrc,
+ "Retrieving damaged sub-region @ %d,%d size %dx%d",
+ rects[i].x, rects[i].y, rects[i].width, rects[i].height);
+
+ XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
+ rects[i].x, rects[i].y,
+ rects[i].width, rects[i].height,
+ AllPlanes, ZPixmap, ximage->ximage, rects[i].x, rects[i].y);
+ }
+ }
+ free (rects);
+ }
+ }
+ } while (XPending (ximagesrc->xcontext->disp));
+ if (!have_frame) {
+ GST_LOG_OBJECT (ximagesrc,
+ "Copying from last frame ximage->size: %d",
+ GST_BUFFER_SIZE (GST_BUFFER (ximage)));
+ memcpy (GST_BUFFER_DATA (GST_BUFFER (ximage)),
+ GST_BUFFER_DATA (GST_BUFFER (ximagesrc->last_ximage)),
+ GST_BUFFER_SIZE (GST_BUFFER (ximage)));
+ }
+#ifdef HAVE_XFIXES
+ /* re-get area where last mouse pointer was but only if in our clipping
+ * bounds */
+ if (ximagesrc->cursor_image) {
+ gint x, y, width, height;
+
+ x = ximagesrc->cursor_image->x - ximagesrc->cursor_image->xhot;
+ y = ximagesrc->cursor_image->y - ximagesrc->cursor_image->yhot;
+ width = ximagesrc->cursor_image->width;
+ height = ximagesrc->cursor_image->height;
+
+ /* bounds checking */
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+ if (x + width > ximagesrc->xcontext->width)
+ width = ximagesrc->xcontext->width - x;
+ if (y + height > ximagesrc->xcontext->height)
+ height = ximagesrc->xcontext->height - y;
+ g_assert (x >= 0);
+ g_assert (y >= 0);
+ GST_DEBUG_OBJECT (ximagesrc,
+ "Cursor was at (%d,%d) width: %d, height: %d and our range is: (%d,%d) - (%d,%d)",
+ x, y, width, height, ximagesrc->startx, ximagesrc->starty,
+ ximagesrc->endx, ximagesrc->endy);
+ /* only get where cursor last was, if it is in our range */
+ if (ximagesrc->endx > ximagesrc->startx &&
+ ximagesrc->endy > ximagesrc->starty) {
+ /* check bounds */
+ if (x + width < ximagesrc->startx || x > ximagesrc->endx) {
+ /* trivial reject */
+ } else if (y + height < ximagesrc->starty || y > ximagesrc->endy) {
+ /* trivial reject */
+ } else {
+ /* find intersect region */
+ int startx, starty, iwidth, iheight;
+
+ startx = (x < ximagesrc->startx) ? ximagesrc->startx : x;
+ starty = (y < ximagesrc->starty) ? ximagesrc->starty : y;
+ iwidth = (x + width < ximagesrc->endx) ?
+ x + width - startx : ximagesrc->endx - startx;
+ iheight = (y + height < ximagesrc->endy) ?
+ y + height - starty : ximagesrc->endy - starty;
+ GST_DEBUG_OBJECT (ximagesrc, "Removing cursor from %d,%d", x, y);
+ XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
+ startx, starty, iwidth, iheight, AllPlanes, ZPixmap,
+ ximage->ximage, startx - ximagesrc->startx,
+ starty - ximagesrc->starty);
+ }
+ } else {
+
+ GST_DEBUG_OBJECT (ximagesrc, "Removing cursor from %d,%d", x, y);
+ XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
+ x, y, width, height, AllPlanes, ZPixmap, ximage->ximage, x, y);
+ }
+ }
+#endif
+
+
+ } else {
+#endif
+
+#ifdef HAVE_XSHM
+ if (ximagesrc->xcontext->use_xshm) {
+ GST_DEBUG_OBJECT (ximagesrc, "Retrieving screen using XShm");
+ XShmGetImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
+ ximage->ximage, ximagesrc->startx, ximagesrc->starty, AllPlanes);
+
+ } else
+#endif /* HAVE_XSHM */
+ {
+ GST_DEBUG_OBJECT (ximagesrc, "Retrieving screen using XGetImage");
+ if (ximagesrc->remote) {
+ XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
+ ximagesrc->startx, ximagesrc->starty, ximagesrc->width,
+ ximagesrc->height, AllPlanes, ZPixmap, ximage->ximage, 0, 0);
+ } else {
+ ximage->ximage =
+ XGetImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
+ ximagesrc->startx, ximagesrc->starty, ximagesrc->width,
+ ximagesrc->height, AllPlanes, ZPixmap);
+ }
+ }
+#ifdef HAVE_XDAMAGE
+ }
+#endif
+
+#ifdef HAVE_XFIXES
+ if (ximagesrc->show_pointer && ximagesrc->have_xfixes) {
+
+ GST_DEBUG_OBJECT (ximagesrc, "Using XFixes to draw cursor");
+ /* get cursor */
+ if (ximagesrc->cursor_image)
+ XFree (ximagesrc->cursor_image);
+ ximagesrc->cursor_image = XFixesGetCursorImage (ximagesrc->xcontext->disp);
+ if (ximagesrc->cursor_image != NULL) {
+ int cx, cy, i, j, count;
+ int startx, starty, iwidth, iheight;
+ gboolean cursor_in_image = TRUE;
+
+ cx = ximagesrc->cursor_image->x - ximagesrc->cursor_image->xhot;
+ if (cx < 0)
+ cx = 0;
+ cy = ximagesrc->cursor_image->y - ximagesrc->cursor_image->yhot;
+ if (cy < 0)
+ cy = 0;
+ count = ximagesrc->cursor_image->width * ximagesrc->cursor_image->height;
+
+ /* only get where cursor last was, if it is in our range */
+ if (ximagesrc->endx > ximagesrc->startx &&
+ ximagesrc->endy > ximagesrc->starty) {
+ /* check bounds */
+ if (cx + ximagesrc->cursor_image->width < ximagesrc->startx ||
+ cx > ximagesrc->endx) {
+ /* trivial reject */
+ cursor_in_image = FALSE;
+ } else if (cy + ximagesrc->cursor_image->height < ximagesrc->starty ||
+ cy > ximagesrc->endy) {
+ /* trivial reject */
+ cursor_in_image = FALSE;
+ } else {
+ /* find intersect region */
+
+ startx = (cx < ximagesrc->startx) ? ximagesrc->startx : cx;
+ starty = (cy < ximagesrc->starty) ? ximagesrc->starty : cy;
+ iwidth = (cx + ximagesrc->cursor_image->width < ximagesrc->endx) ?
+ cx + ximagesrc->cursor_image->width - startx :
+ ximagesrc->endx - startx;
+ iheight = (cy + ximagesrc->cursor_image->height < ximagesrc->endy) ?
+ cy + ximagesrc->cursor_image->height - starty :
+ ximagesrc->endy - starty;
+ }
+ } else {
+ startx = cx;
+ starty = cy;
+ iwidth = ximagesrc->cursor_image->width;
+ iheight = ximagesrc->cursor_image->height;
+ }
+
+ if (cursor_in_image) {
+ GST_DEBUG_OBJECT (ximagesrc, "Cursor is in image so trying to draw it");
+ for (i = 0; i < count; i++)
+ ximagesrc->cursor_image->pixels[i] =
+ GUINT_TO_LE (ximagesrc->cursor_image->pixels[i]);
+ /* copy those pixels across */
+ for (j = starty;
+ j < starty + iheight && j < ximagesrc->starty + ximagesrc->height;
+ j++) {
+ for (i = startx;
+ i < startx + iwidth && i < ximagesrc->startx + ximagesrc->width;
+ i++) {
+ guint8 *src, *dest;
+
+ src =
+ (guint8 *) & (ximagesrc->cursor_image->pixels[((j -
+ cy) * ximagesrc->cursor_image->width + (i - cx))]);
+ dest =
+ (guint8 *) & (ximage->ximage->data[((j -
+ ximagesrc->starty) * ximagesrc->width + (i -
+ ximagesrc->startx)) * (ximagesrc->xcontext->bpp /
+ 8)]);
+
+ composite_pixel (ximagesrc->xcontext, (guint8 *) dest,
+ (guint8 *) src);
+ }
+ }
+ }
+ }
+ }
+#endif
+#ifdef HAVE_XDAMAGE
+ if (ximagesrc->have_xdamage && ximagesrc->use_damage) {
+ /* need to ref ximage to put in last_ximage */
+ gst_buffer_ref (GST_BUFFER (ximage));
+ if (ximagesrc->last_ximage) {
+ gst_buffer_unref (GST_BUFFER (ximagesrc->last_ximage));
+ }
+ ximagesrc->last_ximage = ximage;
+ GST_LOG_OBJECT (ximagesrc, "reffing current buffer for last_ximage");
+ }
+#endif
+ return ximage;
+}
+
+static GstFlowReturn
+gst_ximage_src_create (GstPushSrc * bs, GstBuffer ** buf)
+{
+ GstXImageSrc *s = GST_XIMAGE_SRC (bs);
+ GstXImageSrcBuffer *image;
+ GstClockTime base_time;
+ GstClockTime next_capture_ts;
+ GstClockTime dur;
+ gint64 next_frame_no;
+
+ if (!gst_ximage_src_recalc (s)) {
+ GST_ELEMENT_ERROR (s, RESOURCE, FAILED,
+ (_("Changing resolution at runtime is not yet supported.")), (NULL));
+ return GST_FLOW_ERROR;
+ }
+
+ if (s->fps_n <= 0 || s->fps_d <= 0)
+ return GST_FLOW_NOT_NEGOTIATED; /* FPS must be > 0 */
+
+ /* Now, we might need to wait for the next multiple of the fps
+ * before capturing */
+
+ GST_OBJECT_LOCK (s);
+ if (GST_ELEMENT_CLOCK (s) == NULL) {
+ GST_OBJECT_UNLOCK (s);
+ GST_ELEMENT_ERROR (s, RESOURCE, FAILED,
+ (_("Cannot operate without a clock")), (NULL));
+ return GST_FLOW_ERROR;
+ }
+
+ base_time = GST_ELEMENT_CAST (s)->base_time;
+ next_capture_ts = gst_clock_get_time (GST_ELEMENT_CLOCK (s));
+ next_capture_ts -= base_time;
+
+ /* Figure out which 'frame number' position we're at, based on the cur time
+ * and frame rate */
+ next_frame_no = gst_util_uint64_scale (next_capture_ts,
+ s->fps_n, GST_SECOND * s->fps_d);
+ if (next_frame_no == s->last_frame_no) {
+ GstClockID id;
+ GstClockReturn ret;
+
+ /* Need to wait for the next frame */
+ next_frame_no += 1;
+
+ /* Figure out what the next frame time is */
+ next_capture_ts = gst_util_uint64_scale (next_frame_no,
+ s->fps_d * GST_SECOND, s->fps_n);
+
+ id = gst_clock_new_single_shot_id (GST_ELEMENT_CLOCK (s),
+ next_capture_ts + base_time);
+ s->clock_id = id;
+
+ /* release the object lock while waiting */
+ GST_OBJECT_UNLOCK (s);
+
+ GST_DEBUG_OBJECT (s, "Waiting for next frame time %" G_GUINT64_FORMAT,
+ next_capture_ts);
+ ret = gst_clock_id_wait (id, NULL);
+ GST_OBJECT_LOCK (s);
+
+ gst_clock_id_unref (id);
+ s->clock_id = NULL;
+ if (ret == GST_CLOCK_UNSCHEDULED) {
+ /* Got woken up by the unlock function */
+ GST_OBJECT_UNLOCK (s);
+ return GST_FLOW_WRONG_STATE;
+ }
+ /* Duration is a complete 1/fps frame duration */
+ dur = gst_util_uint64_scale_int (GST_SECOND, s->fps_d, s->fps_n);
+ } else {
+ GstClockTime next_frame_ts;
+
+ GST_DEBUG_OBJECT (s, "No need to wait for next frame time %"
+ G_GUINT64_FORMAT " next frame = %" G_GINT64_FORMAT " prev = %"
+ G_GINT64_FORMAT, next_capture_ts, next_frame_no, s->last_frame_no);
+ next_frame_ts = gst_util_uint64_scale (next_frame_no + 1,
+ s->fps_d * GST_SECOND, s->fps_n);
+ /* Frame duration is from now until the next expected capture time */
+ dur = next_frame_ts - next_capture_ts;
+ }
+ s->last_frame_no = next_frame_no;
+ GST_OBJECT_UNLOCK (s);
+
+ image = gst_ximage_src_ximage_get (s);
+ if (!image)
+ return GST_FLOW_ERROR;
+
+ *buf = GST_BUFFER (image);
+ GST_BUFFER_TIMESTAMP (*buf) = next_capture_ts;
+ GST_BUFFER_DURATION (*buf) = dur;
+
+ return GST_FLOW_OK;
+}
+
+static void
+gst_ximage_src_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstXImageSrc *src = GST_XIMAGE_SRC (object);
+
+ switch (prop_id) {
+ case PROP_DISPLAY_NAME:
+
+ g_free (src->display_name);
+ src->display_name = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_SCREEN_NUM:
+ src->screen_num = g_value_get_uint (value);
+ break;
+ case PROP_SHOW_POINTER:
+ src->show_pointer = g_value_get_boolean (value);
+ break;
+ case PROP_USE_DAMAGE:
+ src->use_damage = g_value_get_boolean (value);
+ break;
+ case PROP_STARTX:
+ src->startx = g_value_get_uint (value);
+ break;
+ case PROP_STARTY:
+ src->starty = g_value_get_uint (value);
+ break;
+ case PROP_ENDX:
+ src->endx = g_value_get_uint (value);
+ break;
+ case PROP_ENDY:
+ src->endy = g_value_get_uint (value);
+ break;
+ case PROP_REMOTE:
+ src->remote = g_value_get_boolean (value);
+ break;
+ case PROP_XID:
+ if (src->xcontext != NULL) {
+ g_warning ("ximagesrc window ID must be set before opening display");
+ break;
+ }
+ src->xid = g_value_get_uint64 (value);
+ break;
+ case PROP_XNAME:
+ if (src->xcontext != NULL) {
+ g_warning ("ximagesrc window name must be set before opening display");
+ break;
+ }
+ g_free (src->xname);
+ src->xname = g_strdup (g_value_get_string (value));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+gst_ximage_src_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstXImageSrc *src = GST_XIMAGE_SRC (object);
+
+ switch (prop_id) {
+ case PROP_DISPLAY_NAME:
+ if (src->xcontext)
+ g_value_set_string (value, DisplayString (src->xcontext->disp));
+ else
+ g_value_set_string (value, src->display_name);
+
+ break;
+ case PROP_SCREEN_NUM:
+ g_value_set_uint (value, src->screen_num);
+ break;
+ case PROP_SHOW_POINTER:
+ g_value_set_boolean (value, src->show_pointer);
+ break;
+ case PROP_USE_DAMAGE:
+ g_value_set_boolean (value, src->use_damage);
+ break;
+ case PROP_STARTX:
+ g_value_set_uint (value, src->startx);
+ break;
+ case PROP_STARTY:
+ g_value_set_uint (value, src->starty);
+ break;
+ case PROP_ENDX:
+ g_value_set_uint (value, src->endx);
+ break;
+ case PROP_ENDY:
+ g_value_set_uint (value, src->endy);
+ break;
+ case PROP_REMOTE:
+ g_value_set_boolean (value, src->remote);
+ break;
+ case PROP_XID:
+ g_value_set_uint64 (value, src->xid);
+ break;
+ case PROP_XNAME:
+ g_value_set_string (value, src->xname);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_ximage_src_clear_bufpool (GstXImageSrc * ximagesrc)
+{
+ g_mutex_lock (ximagesrc->pool_lock);
+ while (ximagesrc->buffer_pool != NULL) {
+ GstXImageSrcBuffer *ximage = ximagesrc->buffer_pool->data;
+
+ gst_ximage_buffer_free (ximage);
+
+ ximagesrc->buffer_pool = g_slist_delete_link (ximagesrc->buffer_pool,
+ ximagesrc->buffer_pool);
+ }
+ g_mutex_unlock (ximagesrc->pool_lock);
+}
+
+static void
+gst_ximage_src_base_init (gpointer g_class)
+{
+ GstElementClass *ec = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_set_details_simple (ec, "Ximage video source",
+ "Source/Video",
+ "Creates a screenshot video stream",
+ "Lutz Mueller <lutz@users.sourceforge.net>, "
+ "Jan Schmidt <thaytan@mad.scientist.com>, "
+ "Zaheer Merali <zaheerabbas at merali dot org>");
+ gst_element_class_add_static_pad_template (ec, &t);
+}
+
+static void
+gst_ximage_src_dispose (GObject * object)
+{
+ /* Drop references in the buffer_pool */
+ gst_ximage_src_clear_bufpool (GST_XIMAGE_SRC (object));
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_ximage_src_finalize (GObject * object)
+{
+ GstXImageSrc *src = GST_XIMAGE_SRC (object);
+
+ if (src->xcontext)
+ ximageutil_xcontext_clear (src->xcontext);
+
+ g_free (src->xname);
+ g_mutex_free (src->pool_lock);
+ g_mutex_free (src->x_lock);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static GstCaps *
+gst_ximage_src_get_caps (GstBaseSrc * bs)
+{
+ GstXImageSrc *s = GST_XIMAGE_SRC (bs);
+ GstXContext *xcontext;
+ gint width, height;
+
+ if ((!s->xcontext) && (!gst_ximage_src_open_display (s, s->display_name)))
+ return
+ gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC
+ (s)->srcpad));
+
+ if (!gst_ximage_src_recalc (s))
+ return
+ gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC
+ (s)->srcpad));
+
+ xcontext = s->xcontext;
+ width = s->xcontext->width;
+ height = s->xcontext->height;
+ if (s->xwindow != 0) {
+ XWindowAttributes attrs;
+ int status = XGetWindowAttributes (s->xcontext->disp, s->xwindow, &attrs);
+ if (status) {
+ width = attrs.width;
+ height = attrs.height;
+ }
+ }
+
+ /* property comments say 0 means right/bottom, means we can't capture
+ the top left pixel alone */
+ if (s->endx == 0)
+ s->endx = width - 1;
+ if (s->endy == 0)
+ s->endy = height - 1;
+
+ if (s->endx >= s->startx && s->endy >= s->starty) {
+ /* this means user has put in values */
+ if (s->startx < xcontext->width && s->endx < xcontext->width &&
+ s->starty < xcontext->height && s->endy < xcontext->height &&
+ s->startx >= 0 && s->starty >= 0) {
+ /* values are fine */
+ s->width = width = s->endx - s->startx + 1;
+ s->height = height = s->endy - s->starty + 1;
+ } else {
+ GST_WARNING
+ ("User put in co-ordinates overshooting the X resolution, setting to full screen");
+ s->startx = 0;
+ s->starty = 0;
+ s->endx = width - 1;
+ s->endy = height - 1;
+ }
+ } else {
+ GST_WARNING ("User put in bogus co-ordinates, setting to full screen");
+ s->startx = 0;
+ s->starty = 0;
+ s->endx = width - 1;
+ s->endy = height - 1;
+ }
+ GST_DEBUG ("width = %d, height=%d", width, height);
+ return gst_caps_new_simple ("video/x-raw-rgb",
+ "bpp", G_TYPE_INT, xcontext->bpp,
+ "depth", G_TYPE_INT, xcontext->depth,
+ "endianness", G_TYPE_INT, xcontext->endianness,
+ "red_mask", G_TYPE_INT, xcontext->r_mask_output,
+ "green_mask", G_TYPE_INT, xcontext->g_mask_output,
+ "blue_mask", G_TYPE_INT, xcontext->b_mask_output,
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ "framerate", GST_TYPE_FRACTION_RANGE, 1, G_MAXINT, G_MAXINT, 1,
+ "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 1, G_MAXINT, G_MAXINT, 1,
+ NULL);
+}
+
+static gboolean
+gst_ximage_src_set_caps (GstBaseSrc * bs, GstCaps * caps)
+{
+ GstXImageSrc *s = GST_XIMAGE_SRC (bs);
+ GstStructure *structure;
+ const GValue *new_fps;
+
+ /* If not yet opened, disallow setcaps until later */
+ if (!s->xcontext)
+ return FALSE;
+
+ /* The only thing that can change is the framerate downstream wants */
+ structure = gst_caps_get_structure (caps, 0);
+ new_fps = gst_structure_get_value (structure, "framerate");
+ if (!new_fps)
+ return FALSE;
+
+ /* Store this FPS for use when generating buffers */
+ s->fps_n = gst_value_get_fraction_numerator (new_fps);
+ s->fps_d = gst_value_get_fraction_denominator (new_fps);
+
+ GST_DEBUG_OBJECT (s, "peer wants %d/%d fps", s->fps_n, s->fps_d);
+
+ return TRUE;
+}
+
+static void
+gst_ximage_src_fixate (GstPad * pad, GstCaps * caps)
+{
+ gint i;
+ GstStructure *structure;
+
+ for (i = 0; i < gst_caps_get_size (caps); ++i) {
+ structure = gst_caps_get_structure (caps, i);
+
+ gst_structure_fixate_field_nearest_fraction (structure, "framerate", 25, 1);
+ }
+}
+
+static void
+gst_ximage_src_class_init (GstXImageSrcClass * klass)
+{
+ GObjectClass *gc = G_OBJECT_CLASS (klass);
+ GstBaseSrcClass *bc = GST_BASE_SRC_CLASS (klass);
+ GstPushSrcClass *push_class = GST_PUSH_SRC_CLASS (klass);
+
+ gc->set_property = gst_ximage_src_set_property;
+ gc->get_property = gst_ximage_src_get_property;
+ gc->dispose = gst_ximage_src_dispose;
+ gc->finalize = gst_ximage_src_finalize;
+
+ g_object_class_install_property (gc, PROP_DISPLAY_NAME,
+ g_param_spec_string ("display-name", "Display", "X Display Name", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gc, PROP_SCREEN_NUM,
+ g_param_spec_uint ("screen-num", "Screen number", "X Screen Number",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gc, PROP_SHOW_POINTER,
+ g_param_spec_boolean ("show-pointer", "Show Mouse Pointer",
+ "Show mouse pointer (if XFixes extension enabled)", TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstXImageSrc:use-damage
+ *
+ * Use XDamage (if the XDamage extension is enabled)
+ *
+ * Since: 0.10.4
+ **/
+ g_object_class_install_property (gc, PROP_USE_DAMAGE,
+ g_param_spec_boolean ("use-damage", "Use XDamage",
+ "Use XDamage (if XDamage extension enabled)", TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstXImageSrc:startx
+ *
+ * X coordinate of top left corner of area to be recorded
+ * (0 for top left of screen)
+ *
+ * Since: 0.10.4
+ **/
+ g_object_class_install_property (gc, PROP_STARTX,
+ g_param_spec_uint ("startx", "Start X co-ordinate",
+ "X coordinate of top left corner of area to be recorded (0 for top left of screen)",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstXImageSrc:starty
+ *
+ * Y coordinate of top left corner of area to be recorded
+ * (0 for top left of screen)
+ *
+ * Since: 0.10.4
+ **/
+ g_object_class_install_property (gc, PROP_STARTY,
+ g_param_spec_uint ("starty", "Start Y co-ordinate",
+ "Y coordinate of top left corner of area to be recorded (0 for top left of screen)",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE));
+ /**
+ * GstXImageSrc:endx
+ *
+ * X coordinate of bottom right corner of area to be recorded
+ * (0 for bottom right of screen)
+ *
+ * Since: 0.10.4
+ **/
+ g_object_class_install_property (gc, PROP_ENDX,
+ g_param_spec_uint ("endx", "End X",
+ "X coordinate of bottom right corner of area to be recorded (0 for bottom right of screen)",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE));
+ /**
+ * GstXImageSrc:endy
+ *
+ * Y coordinate of bottom right corner of area to be recorded
+ * (0 for bottom right of screen)
+ *
+ * Since: 0.10.4
+ **/
+ g_object_class_install_property (gc, PROP_ENDY,
+ g_param_spec_uint ("endy", "End Y",
+ "Y coordinate of bottom right corner of area to be recorded (0 for bottom right of screen)",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE));
+
+ /**
+ * GstXImageSrc:remote
+ *
+ * Whether the X display is remote. The element will try to use alternate calls
+ * known to work better with remote displays.
+ *
+ * Since: 0.10.26
+ **/
+ g_object_class_install_property (gc, PROP_REMOTE,
+ g_param_spec_boolean ("remote", "Remote dispay",
+ "Whether the display is remote", FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GstXImageSrc:xid
+ *
+ * The XID of the window to capture. 0 for the root window (default).
+ *
+ * Since: 0.10.31
+ **/
+ g_object_class_install_property (gc, PROP_XID,
+ g_param_spec_uint64 ("xid", "Window XID",
+ "Window XID to capture from", 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GstXImageSrc:xname
+ *
+ * The name of the window to capture, if any.
+ *
+ * Since: 0.10.31
+ **/
+ g_object_class_install_property (gc, PROP_XNAME,
+ g_param_spec_string ("xname", "Window name",
+ "Window name to capture from", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ push_class->create = gst_ximage_src_create;
+ bc->get_caps = gst_ximage_src_get_caps;
+ bc->set_caps = gst_ximage_src_set_caps;
+ bc->start = gst_ximage_src_start;
+ bc->stop = gst_ximage_src_stop;
+ bc->unlock = gst_ximage_src_unlock;
+}
+
+static void
+gst_ximage_src_init (GstXImageSrc * ximagesrc, GstXImageSrcClass * klass)
+{
+ gst_base_src_set_format (GST_BASE_SRC (ximagesrc), GST_FORMAT_TIME);
+ gst_base_src_set_live (GST_BASE_SRC (ximagesrc), TRUE);
+ gst_pad_set_fixatecaps_function (GST_BASE_SRC_PAD (ximagesrc),
+ gst_ximage_src_fixate);
+
+ ximagesrc->pool_lock = g_mutex_new ();
+ ximagesrc->x_lock = g_mutex_new ();
+ ximagesrc->show_pointer = TRUE;
+ ximagesrc->use_damage = TRUE;
+ ximagesrc->startx = 0;
+ ximagesrc->starty = 0;
+ ximagesrc->endx = 0;
+ ximagesrc->endy = 0;
+ ximagesrc->remote = FALSE;
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ gboolean ret;
+
+ GST_DEBUG_CATEGORY_INIT (gst_debug_ximage_src, "ximagesrc", 0,
+ "ximagesrc element debug");
+
+ ret = gst_element_register (plugin, "ximagesrc", GST_RANK_NONE,
+ GST_TYPE_XIMAGE_SRC);
+
+ return ret;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "ximagesrc",
+ "X11 video input plugin using standard Xlib calls",
+ plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
diff --git a/sys/ximage/gstximagesrc.h b/sys/ximage/gstximagesrc.h
new file mode 100644
index 0000000..e58513c
--- /dev/null
+++ b/sys/ximage/gstximagesrc.h
@@ -0,0 +1,113 @@
+/* screenshotsrc: Screenshot plugin for GStreamer
+ *
+ * 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.
+ */
+
+#ifndef __GST_XIMAGE_SRC_H__
+#define __GST_XIMAGE_SRC_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstpushsrc.h>
+#include "ximageutil.h"
+
+#ifdef HAVE_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif
+#ifdef HAVE_XDAMAGE
+#include <X11/extensions/Xdamage.h>
+#endif
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_XIMAGE_SRC (gst_ximage_src_get_type())
+#define GST_XIMAGE_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_XIMAGE_SRC,GstXImageSrc))
+#define GST_XIMAGE_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_XIMAGE_SRC,GstXImageSrc))
+#define GST_IS_XIMAGE_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_XIMAGE_SRC))
+#define GST_IS_XIMAGE_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_XIMAGE_SRC))
+
+typedef struct _GstXImageSrc GstXImageSrc;
+typedef struct _GstXImageSrcClass GstXImageSrcClass;
+
+GType gst_ximage_src_get_type (void) G_GNUC_CONST;
+
+struct _GstXImageSrc
+{
+ GstPushSrc parent;
+
+ /* Information on display */
+ GstXContext *xcontext;
+ gint width;
+ gint height;
+
+ Window xwindow;
+ gchar *display_name;
+ guint screen_num;
+
+ /* Window selection */
+ guint64 xid;
+ gchar *xname;
+
+ /* Desired output framerate */
+ gint fps_n;
+ gint fps_d;
+
+ /* for framerate sync */
+ GstClockID clock_id;
+ gint64 last_frame_no;
+
+ /* Protect X Windows calls */
+ GMutex *x_lock;
+
+ /* Gathered pool of emitted buffers */
+ GMutex *pool_lock;
+ GSList *buffer_pool;
+
+ /* XFixes and XDamage support */
+ gboolean have_xfixes;
+ gboolean have_xdamage;
+ gboolean show_pointer;
+ gboolean use_damage;
+
+ /* co-ordinates for start and end */
+ guint startx;
+ guint starty;
+ guint endx;
+ guint endy;
+
+ /* whether to use remote friendly calls */
+ gboolean remote;
+
+#ifdef HAVE_XFIXES
+ int fixes_event_base;
+ XFixesCursorImage *cursor_image;
+#endif
+#ifdef HAVE_XDAMAGE
+ Damage damage;
+ int damage_event_base;
+ XserverRegion damage_region;
+ GC damage_copy_gc;
+ GstXImageSrcBuffer *last_ximage;
+#endif
+};
+
+struct _GstXImageSrcClass
+{
+ GstPushSrcClass parent_class;
+};
+
+G_END_DECLS
+
+#endif /* __GST_XIMAGE_SRC_H__ */
diff --git a/sys/ximage/ximageutil.c b/sys/ximage/ximageutil.c
new file mode 100644
index 0000000..2fac09a
--- /dev/null
+++ b/sys/ximage/ximageutil.c
@@ -0,0 +1,501 @@
+/* GStreamer
+ * Copyright (C) <2005> Luca Ognibene <luogni@tin.it>
+ *
+ * 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 "ximageutil.h"
+
+#ifdef HAVE_XSHM
+static gboolean error_caught = FALSE;
+
+static int
+ximageutil_handle_xerror (Display * display, XErrorEvent * xevent)
+{
+ char error_msg[1024];
+
+ XGetErrorText (display, xevent->error_code, error_msg, 1024);
+ GST_DEBUG ("ximageutil failed to use XShm calls. error: %s", error_msg);
+ error_caught = TRUE;
+ return 0;
+}
+
+/* This function checks that it is actually really possible to create an image
+ using XShm */
+gboolean
+ximageutil_check_xshm_calls (GstXContext * xcontext)
+{
+ XImage *ximage;
+ XShmSegmentInfo SHMInfo;
+ size_t size;
+ int (*handler) (Display *, XErrorEvent *);
+ gboolean result = FALSE;
+ gboolean did_attach = FALSE;
+
+ g_return_val_if_fail (xcontext != NULL, FALSE);
+
+ /* Sync to ensure any older errors are already processed */
+ XSync (xcontext->disp, FALSE);
+
+ /* Set defaults so we don't free these later unnecessarily */
+ SHMInfo.shmaddr = ((void *) -1);
+ SHMInfo.shmid = -1;
+
+ /* Setting an error handler to catch failure */
+ error_caught = FALSE;
+ handler = XSetErrorHandler (ximageutil_handle_xerror);
+
+ /* Trying to create a 1x1 ximage */
+ GST_DEBUG ("XShmCreateImage of 1x1");
+
+ ximage = XShmCreateImage (xcontext->disp, xcontext->visual,
+ xcontext->depth, ZPixmap, NULL, &SHMInfo, 1, 1);
+
+ /* Might cause an error, sync to ensure it is noticed */
+ XSync (xcontext->disp, FALSE);
+ if (!ximage || error_caught) {
+ GST_WARNING ("could not XShmCreateImage a 1x1 image");
+ goto beach;
+ }
+ size = ximage->height * ximage->bytes_per_line;
+
+ SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
+ if (SHMInfo.shmid == -1) {
+ GST_WARNING ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
+ size);
+ goto beach;
+ }
+
+ SHMInfo.shmaddr = shmat (SHMInfo.shmid, 0, 0);
+ if (SHMInfo.shmaddr == ((void *) -1)) {
+ GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
+ goto beach;
+ }
+
+ /* Delete the SHM segment. It will actually go away automatically
+ * when we detach now */
+ shmctl (SHMInfo.shmid, IPC_RMID, 0);
+
+ ximage->data = SHMInfo.shmaddr;
+ SHMInfo.readOnly = FALSE;
+
+ if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
+ GST_WARNING ("Failed to XShmAttach");
+ goto beach;
+ }
+
+ /* Sync to ensure we see any errors we caused */
+ XSync (xcontext->disp, FALSE);
+
+ if (!error_caught) {
+ did_attach = TRUE;
+ /* store whether we succeeded in result */
+ result = TRUE;
+ }
+beach:
+ /* Sync to ensure we swallow any errors we caused and reset error_caught */
+ XSync (xcontext->disp, FALSE);
+ error_caught = FALSE;
+ XSetErrorHandler (handler);
+
+ if (did_attach) {
+ XShmDetach (xcontext->disp, &SHMInfo);
+ XSync (xcontext->disp, FALSE);
+ }
+ if (SHMInfo.shmaddr != ((void *) -1))
+ shmdt (SHMInfo.shmaddr);
+ if (ximage)
+ XDestroyImage (ximage);
+ return result;
+}
+#endif /* HAVE_XSHM */
+
+/* This function gets the X Display and global info about it. Everything is
+ stored in our object and will be cleaned when the object is disposed. Note
+ here that caps for supported format are generated without any window or
+ image creation */
+GstXContext *
+ximageutil_xcontext_get (GstElement * parent, const gchar * display_name)
+{
+ GstXContext *xcontext = NULL;
+ XPixmapFormatValues *px_formats = NULL;
+ gint nb_formats = 0, i;
+
+ xcontext = g_new0 (GstXContext, 1);
+
+ xcontext->disp = XOpenDisplay (display_name);
+ GST_DEBUG_OBJECT (parent, "opened display %p", xcontext->disp);
+ if (!xcontext->disp) {
+ g_free (xcontext);
+ return NULL;
+ }
+ xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
+ xcontext->screen_num = DefaultScreen (xcontext->disp);
+ xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
+ xcontext->root = DefaultRootWindow (xcontext->disp);
+ xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num);
+ xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num);
+ xcontext->depth = DefaultDepthOfScreen (xcontext->screen);
+
+ xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num);
+ xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num);
+
+ xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num);
+ xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num);
+
+ xcontext->caps = NULL;
+
+ GST_DEBUG_OBJECT (parent, "X reports %dx%d pixels and %d mm x %d mm",
+ xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm);
+ ximageutil_calculate_pixel_aspect_ratio (xcontext);
+
+ /* We get supported pixmap formats at supported depth */
+ px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
+
+ if (!px_formats) {
+ XCloseDisplay (xcontext->disp);
+ g_free (xcontext);
+ return NULL;
+ }
+
+ /* We get bpp value corresponding to our running depth */
+ for (i = 0; i < nb_formats; i++) {
+ if (px_formats[i].depth == xcontext->depth)
+ xcontext->bpp = px_formats[i].bits_per_pixel;
+ }
+
+ XFree (px_formats);
+
+ xcontext->endianness =
+ (ImageByteOrder (xcontext->disp) ==
+ LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
+
+#ifdef HAVE_XSHM
+ /* Search for XShm extension support */
+ if (XShmQueryExtension (xcontext->disp) &&
+ ximageutil_check_xshm_calls (xcontext)) {
+ xcontext->use_xshm = TRUE;
+ GST_DEBUG ("ximageutil is using XShm extension");
+ } else {
+ xcontext->use_xshm = FALSE;
+ GST_DEBUG ("ximageutil is not using XShm extension");
+ }
+#endif /* HAVE_XSHM */
+
+ /* our caps system handles 24/32bpp RGB as big-endian. */
+ if ((xcontext->bpp == 24 || xcontext->bpp == 32) &&
+ xcontext->endianness == G_LITTLE_ENDIAN) {
+ xcontext->endianness = G_BIG_ENDIAN;
+ xcontext->r_mask_output = GUINT32_TO_BE (xcontext->visual->red_mask);
+ xcontext->g_mask_output = GUINT32_TO_BE (xcontext->visual->green_mask);
+ xcontext->b_mask_output = GUINT32_TO_BE (xcontext->visual->blue_mask);
+ if (xcontext->bpp == 24) {
+ xcontext->r_mask_output >>= 8;
+ xcontext->g_mask_output >>= 8;
+ xcontext->b_mask_output >>= 8;
+ }
+ } else {
+ xcontext->r_mask_output = xcontext->visual->red_mask;
+ xcontext->g_mask_output = xcontext->visual->green_mask;
+ xcontext->b_mask_output = xcontext->visual->blue_mask;
+ }
+
+ return xcontext;
+}
+
+/* This function cleans the X context. Closing the Display and unrefing the
+ caps for supported formats. */
+void
+ximageutil_xcontext_clear (GstXContext * xcontext)
+{
+ g_return_if_fail (xcontext != NULL);
+
+ if (xcontext->caps != NULL)
+ gst_caps_unref (xcontext->caps);
+
+ if (xcontext->par) {
+ g_value_unset (xcontext->par);
+ g_free (xcontext->par);
+ }
+
+ XCloseDisplay (xcontext->disp);
+
+ g_free (xcontext);
+}
+
+/* This function calculates the pixel aspect ratio based on the properties
+ * in the xcontext structure and stores it there. */
+void
+ximageutil_calculate_pixel_aspect_ratio (GstXContext * xcontext)
+{
+ gint par[][2] = {
+ {1, 1}, /* regular screen */
+ {16, 15}, /* PAL TV */
+ {11, 10}, /* 525 line Rec.601 video */
+ {54, 59} /* 625 line Rec.601 video */
+ };
+ gint i;
+ gint index;
+ gdouble ratio;
+ gdouble delta;
+
+#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
+
+ /* first calculate the "real" ratio based on the X values;
+ * which is the "physical" w/h divided by the w/h in pixels of the display */
+ ratio = (gdouble) (xcontext->widthmm * xcontext->height)
+ / (xcontext->heightmm * xcontext->width);
+
+ /* DirectFB's X in 720x576 reports the physical dimensions wrong, so
+ * override here */
+ if (xcontext->width == 720 && xcontext->height == 576) {
+ ratio = 4.0 * 576 / (3.0 * 720);
+ }
+ GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
+
+ /* now find the one from par[][2] with the lowest delta to the real one */
+ delta = DELTA (0);
+ index = 0;
+
+ for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
+ gdouble this_delta = DELTA (i);
+
+ if (this_delta < delta) {
+ index = i;
+ delta = this_delta;
+ }
+ }
+
+ GST_DEBUG ("Decided on index %d (%d/%d)", index,
+ par[index][0], par[index][1]);
+
+ if (xcontext->par)
+ g_free (xcontext->par);
+ xcontext->par = g_new0 (GValue, 1);
+ g_value_init (xcontext->par, GST_TYPE_FRACTION);
+ gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]);
+ GST_DEBUG ("set xcontext PAR to %d/%d\n",
+ gst_value_get_fraction_numerator (xcontext->par),
+ gst_value_get_fraction_denominator (xcontext->par));
+}
+
+static GstBufferClass *ximagesrc_buffer_parent_class = NULL;
+
+static void
+gst_ximagesrc_buffer_finalize (GstXImageSrcBuffer * ximage)
+{
+ GstElement *parent;
+
+ g_return_if_fail (ximage != NULL);
+
+ parent = ximage->parent;
+ if (parent == NULL) {
+ g_warning ("XImageSrcBuffer->ximagesrc == NULL");
+ goto beach;
+ }
+
+ if (ximage->return_func)
+ ximage->return_func (parent, ximage);
+
+beach:
+
+ GST_MINI_OBJECT_CLASS (ximagesrc_buffer_parent_class)->finalize
+ (GST_MINI_OBJECT (ximage));
+
+ return;
+}
+
+void
+gst_ximage_buffer_free (GstXImageSrcBuffer * ximage)
+{
+ /* make sure it is not recycled */
+ ximage->width = -1;
+ ximage->height = -1;
+ gst_buffer_unref (GST_BUFFER (ximage));
+}
+
+static void
+gst_ximagesrc_buffer_init (GstXImageSrcBuffer * ximage_buffer, gpointer g_class)
+{
+#ifdef HAVE_XSHM
+ ximage_buffer->SHMInfo.shmaddr = ((void *) -1);
+ ximage_buffer->SHMInfo.shmid = -1;
+#endif
+}
+
+static void
+gst_ximagesrc_buffer_class_init (gpointer g_class, gpointer class_data)
+{
+ GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
+
+ ximagesrc_buffer_parent_class = g_type_class_peek_parent (g_class);
+
+ mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
+ gst_ximagesrc_buffer_finalize;
+}
+
+static GType
+gst_ximagesrc_buffer_get_type (void)
+{
+ static GType _gst_ximagesrc_buffer_type;
+
+ if (G_UNLIKELY (_gst_ximagesrc_buffer_type == 0)) {
+ static const GTypeInfo ximagesrc_buffer_info = {
+ sizeof (GstBufferClass),
+ NULL,
+ NULL,
+ gst_ximagesrc_buffer_class_init,
+ NULL,
+ NULL,
+ sizeof (GstXImageSrcBuffer),
+ 0,
+ (GInstanceInitFunc) gst_ximagesrc_buffer_init,
+ NULL
+ };
+ _gst_ximagesrc_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
+ "GstXImageSrcBuffer", &ximagesrc_buffer_info, 0);
+ }
+ return _gst_ximagesrc_buffer_type;
+}
+
+/* This function handles GstXImageSrcBuffer creation depending on XShm availability */
+GstXImageSrcBuffer *
+gst_ximageutil_ximage_new (GstXContext * xcontext,
+ GstElement * parent, int width, int height, BufferReturnFunc return_func)
+{
+ GstXImageSrcBuffer *ximage = NULL;
+ gboolean succeeded = FALSE;
+
+ ximage =
+ (GstXImageSrcBuffer *) gst_mini_object_new (GST_TYPE_XIMAGESRC_BUFFER);
+
+ ximage->width = width;
+ ximage->height = height;
+
+#ifdef HAVE_XSHM
+ if (xcontext->use_xshm) {
+ ximage->ximage = XShmCreateImage (xcontext->disp,
+ xcontext->visual, xcontext->depth,
+ ZPixmap, NULL, &ximage->SHMInfo, ximage->width, ximage->height);
+ if (!ximage->ximage) {
+ GST_WARNING_OBJECT (parent,
+ "could not XShmCreateImage a %dx%d image",
+ ximage->width, ximage->height);
+
+ /* Retry without XShm */
+ xcontext->use_xshm = FALSE;
+ goto no_xshm;
+ }
+
+ /* we have to use the returned bytes_per_line for our shm size */
+ ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height;
+ ximage->SHMInfo.shmid = shmget (IPC_PRIVATE, ximage->size,
+ IPC_CREAT | 0777);
+ if (ximage->SHMInfo.shmid == -1)
+ goto beach;
+
+ ximage->SHMInfo.shmaddr = shmat (ximage->SHMInfo.shmid, 0, 0);
+ if (ximage->SHMInfo.shmaddr == ((void *) -1))
+ goto beach;
+
+ /* Delete the SHM segment. It will actually go away automatically
+ * when we detach now */
+ shmctl (ximage->SHMInfo.shmid, IPC_RMID, 0);
+
+ ximage->ximage->data = ximage->SHMInfo.shmaddr;
+ ximage->SHMInfo.readOnly = FALSE;
+
+ if (XShmAttach (xcontext->disp, &ximage->SHMInfo) == 0)
+ goto beach;
+
+ XSync (xcontext->disp, FALSE);
+ } else
+ no_xshm:
+#endif /* HAVE_XSHM */
+ {
+ ximage->ximage = XCreateImage (xcontext->disp,
+ xcontext->visual,
+ xcontext->depth,
+ ZPixmap, 0, NULL, ximage->width, ximage->height, xcontext->bpp, 0);
+ if (!ximage->ximage)
+ goto beach;
+
+ /* we have to use the returned bytes_per_line for our image size */
+ ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height;
+ ximage->ximage->data = g_malloc (ximage->size);
+
+ XSync (xcontext->disp, FALSE);
+ }
+ succeeded = TRUE;
+
+ GST_BUFFER_DATA (ximage) = (guchar *) ximage->ximage->data;
+ GST_BUFFER_SIZE (ximage) = ximage->size;
+
+ /* Keep a ref to our src */
+ ximage->parent = gst_object_ref (parent);
+ ximage->return_func = return_func;
+beach:
+ if (!succeeded) {
+ gst_ximage_buffer_free (ximage);
+ ximage = NULL;
+ }
+
+ return ximage;
+}
+
+/* This function destroys a GstXImageBuffer handling XShm availability */
+void
+gst_ximageutil_ximage_destroy (GstXContext * xcontext,
+ GstXImageSrcBuffer * ximage)
+{
+ /* We might have some buffers destroyed after changing state to NULL */
+ if (!xcontext)
+ goto beach;
+
+ g_return_if_fail (ximage != NULL);
+
+#ifdef HAVE_XSHM
+ if (xcontext->use_xshm) {
+ if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
+ XShmDetach (xcontext->disp, &ximage->SHMInfo);
+ XSync (xcontext->disp, 0);
+ shmdt (ximage->SHMInfo.shmaddr);
+ }
+ if (ximage->ximage)
+ XDestroyImage (ximage->ximage);
+
+ } else
+#endif /* HAVE_XSHM */
+ {
+ if (ximage->ximage) {
+ XDestroyImage (ximage->ximage);
+ }
+ }
+
+ XSync (xcontext->disp, FALSE);
+beach:
+ if (ximage->parent) {
+ /* Release the ref to our parent */
+ gst_object_unref (ximage->parent);
+ ximage->parent = NULL;
+ }
+
+ return;
+}
diff --git a/sys/ximage/ximageutil.h b/sys/ximage/ximageutil.h
new file mode 100644
index 0000000..517fc8e
--- /dev/null
+++ b/sys/ximage/ximageutil.h
@@ -0,0 +1,182 @@
+/* GStreamer
+ * Copyright (C) <2005> Luca Ognibene <luogni@tin.it>
+ *
+ * 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.
+ */
+
+#ifndef __GST_XIMAGEUTIL_H__
+#define __GST_XIMAGEUTIL_H__
+
+#include <gst/gst.h>
+
+#ifdef HAVE_XSHM
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif /* HAVE_XSHM */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef HAVE_XSHM
+#include <X11/extensions/XShm.h>
+#endif /* HAVE_XSHM */
+
+#include <string.h>
+#include <math.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstXContext GstXContext;
+typedef struct _GstXWindow GstXWindow;
+typedef struct _GstXImage GstXImage;
+typedef struct _GstXImageSrcBuffer GstXImageSrcBuffer;
+
+/* Global X Context stuff */
+/**
+ * GstXContext:
+ * @disp: the X11 Display of this context
+ * @screen: the default Screen of Display @disp
+ * @screen_num: the Screen number of @screen
+ * @visual: the default Visual of Screen @screen
+ * @root: the root Window of Display @disp
+ * @white: the value of a white pixel on Screen @screen
+ * @black: the value of a black pixel on Screen @screen
+ * @depth: the color depth of Display @disp
+ * @bpp: the number of bits per pixel on Display @disp
+ * @endianness: the endianness of image bytes on Display @disp
+ * @width: the width in pixels of Display @disp
+ * @height: the height in pixels of Display @disp
+ * @widthmm: the width in millimeters of Display @disp
+ * @heightmm: the height in millimeters of Display @disp
+ * @par: the pixel aspect ratio calculated from @width, @widthmm and @height,
+ * @heightmm ratio
+ * @use_xshm: used to known wether of not XShm extension is usable or not even
+ * if the Extension is present
+ * @caps: the #GstCaps that Display @disp can accept
+ *
+ * Structure used to store various informations collected/calculated for a
+ * Display.
+ */
+struct _GstXContext {
+ Display *disp;
+
+ Screen *screen;
+ gint screen_num;
+
+ Visual *visual;
+
+ Window root;
+
+ gulong white, black;
+
+ gint depth;
+ gint bpp;
+ gint endianness;
+
+ gint width, height;
+ gint widthmm, heightmm;
+
+ /* these are the output masks
+ * for buffers from ximagesrc
+ * and are in big endian */
+ guint32 r_mask_output, g_mask_output, b_mask_output;
+
+ GValue *par; /* calculated pixel aspect ratio */
+
+ gboolean use_xshm;
+
+ GstCaps *caps;
+};
+
+/**
+ * GstXWindow:
+ * @win: the Window ID of this X11 window
+ * @width: the width in pixels of Window @win
+ * @height: the height in pixels of Window @win
+ * @internal: used to remember if Window @win was created internally or passed
+ * through the #GstXOverlay interface
+ * @gc: the Graphical Context of Window @win
+ *
+ * Structure used to store informations about a Window.
+ */
+struct _GstXWindow {
+ Window win;
+ gint width, height;
+ gboolean internal;
+ GC gc;
+};
+
+gboolean ximageutil_check_xshm_calls (GstXContext * xcontext);
+
+GstXContext *ximageutil_xcontext_get (GstElement *parent,
+ const gchar *display_name);
+void ximageutil_xcontext_clear (GstXContext *xcontext);
+void ximageutil_calculate_pixel_aspect_ratio (GstXContext * xcontext);
+
+/* custom ximagesrc buffer, copied from ximagesink */
+
+/* BufferReturnFunc is called when a buffer is finalised */
+typedef void (*BufferReturnFunc) (GstElement *parent, GstXImageSrcBuffer *buf);
+
+/**
+ * GstXImageSrcBuffer:
+ * @parent: a reference to the element we belong to
+ * @ximage: the XImage of this buffer
+ * @width: the width in pixels of XImage @ximage
+ * @height: the height in pixels of XImage @ximage
+ * @size: the size in bytes of XImage @ximage
+ *
+ * Subclass of #GstBuffer containing additional information about an XImage.
+ */
+struct _GstXImageSrcBuffer {
+ GstBuffer buffer;
+
+ /* Reference to the ximagesrc we belong to */
+ GstElement *parent;
+
+ XImage *ximage;
+
+#ifdef HAVE_XSHM
+ XShmSegmentInfo SHMInfo;
+#endif /* HAVE_XSHM */
+
+ gint width, height;
+ size_t size;
+
+ BufferReturnFunc return_func;
+};
+
+
+GstXImageSrcBuffer *gst_ximageutil_ximage_new (GstXContext *xcontext,
+ GstElement *parent, int width, int height, BufferReturnFunc return_func);
+
+void gst_ximageutil_ximage_destroy (GstXContext *xcontext,
+ GstXImageSrcBuffer * ximage);
+
+/* Call to manually release a buffer */
+void gst_ximage_buffer_free (GstXImageSrcBuffer *ximage);
+
+#define GST_TYPE_XIMAGESRC_BUFFER (gst_ximagesrc_buffer_get_type())
+#define GST_IS_XIMAGESRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XIMAGESRC_BUFFER))
+#define GST_IS_XIMAGESRC_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_XIMAGESRC_BUFFER))
+#define GST_XIMAGESRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XIMAGESRC_BUFFER, GstXImageSrcBuffer))
+#define GST_XIMAGESRC_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_XIMAGESRC_BUFFER, GstXImageSrcBufferClass))
+#define GST_XIMAGESRC_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_XIMAGESRC_BUFFER, GstXImageSrcBufferClass))
+
+G_END_DECLS
+
+#endif /* __GST_XIMAGEUTIL_H__ */