From 9b94e38300ef023c12e66aa4df0efa1a8911a92c Mon Sep 17 00:00:00 2001 From: Christian Schaller Date: Mon, 9 Jan 2006 17:04:52 +0000 Subject: [PATCH] add Sun Audio plugin. Verified that nothing breaks and that make check works. Original commit message from CVS: add Sun Audio plugin. Verified that nothing breaks and that make check works. Don't think the docs gets properly built yet, but I don't understand exactly how to enable that. --- ChangeLog | 39 +++ configure.ac | 11 + docs/plugins/gst-plugins-good-plugins-docs.sgml | 3 + docs/upload.mak | 2 +- gst-plugins-good.spec.in | 1 + sys/Makefile.am | 16 +- sys/sunaudio/Makefile.am | 21 ++ sys/sunaudio/gstsunaudio.c | 58 ++++ sys/sunaudio/gstsunaudiomixer.c | 110 +++++++ sys/sunaudio/gstsunaudiomixer.h | 50 +++ sys/sunaudio/gstsunaudiomixerctrl.c | 247 ++++++++++++++ sys/sunaudio/gstsunaudiomixerctrl.h | 142 ++++++++ sys/sunaudio/gstsunaudiomixertrack.c | 109 +++++++ sys/sunaudio/gstsunaudiomixertrack.h | 59 ++++ sys/sunaudio/gstsunaudiosink.c | 411 ++++++++++++++++++++++++ sys/sunaudio/gstsunaudiosink.h | 63 ++++ 16 files changed, 1333 insertions(+), 9 deletions(-) create mode 100644 sys/sunaudio/Makefile.am create mode 100644 sys/sunaudio/gstsunaudio.c create mode 100644 sys/sunaudio/gstsunaudiomixer.c create mode 100644 sys/sunaudio/gstsunaudiomixer.h create mode 100644 sys/sunaudio/gstsunaudiomixerctrl.c create mode 100644 sys/sunaudio/gstsunaudiomixerctrl.h create mode 100644 sys/sunaudio/gstsunaudiomixertrack.c create mode 100644 sys/sunaudio/gstsunaudiomixertrack.h create mode 100644 sys/sunaudio/gstsunaudiosink.c create mode 100644 sys/sunaudio/gstsunaudiosink.h diff --git a/ChangeLog b/ChangeLog index cb05fc4..a5c9949 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,42 @@ +2006-01-09 Brian Cameron + + reviewed by: Christian Schaller + + Add SunAudio plugin - tested to make sure it doesn't break + the build under GNU/Linux. + + * configure.ac: + * gst-plugins-good.spec.in: + * sys/Makefile.am: + * sys/sunaudio/Makefile.am: + * sys/sunaudio/gstsunaudio.c: (plugin_init): + * sys/sunaudio/gstsunaudiomixer.c: (gst_sunaudiomixer_base_init), + (gst_sunaudiomixer_class_init), (gst_sunaudiomixer_init), + (gst_sunaudiomixer_change_state): + * sys/sunaudio/gstsunaudiomixer.h: + * sys/sunaudio/gstsunaudiomixerctrl.c: + (gst_sunaudiomixer_ctrl_open), (gst_sunaudiomixer_ctrl_build_list), + (gst_sunaudiomixer_ctrl_new), (gst_sunaudiomixer_ctrl_free), + (gst_sunaudiomixer_ctrl_list_tracks), + (gst_sunaudiomixer_ctrl_get_volume), + (gst_sunaudiomixer_ctrl_set_volume), + (gst_sunaudiomixer_ctrl_set_mute), + (gst_sunaudiomixer_ctrl_set_record): + * sys/sunaudio/gstsunaudiomixerctrl.h: + * sys/sunaudio/gstsunaudiomixertrack.c: + (gst_sunaudiomixer_track_class_init), + (gst_sunaudiomixer_track_init), (fill_labels), + (gst_sunaudiomixer_track_new): + * sys/sunaudio/gstsunaudiomixertrack.h: + * sys/sunaudio/gstsunaudiosink.c: (gst_sunaudiosink_get_type), + (gst_sunaudiosink_dispose), (gst_sunaudiosink_base_init), + (gst_sunaudiosink_set_property), (gst_sunaudiosink_get_property), + (gst_sunaudiosink_getcaps), (gst_sunaudiosink_open), + (gst_sunaudiosink_close), (gst_sunaudiosink_prepare), + (gst_sunaudiosink_unprepare), (gst_sunaudiosink_write), + (gst_sunaudiosink_delay), (gst_sunaudiosink_reset): + * sys/sunaudio/gstsunaudiosink.h: + 2005-01-07 Philippe Khalaf * gst-plugins-good/gst/udp/gstdynudpsink.c: diff --git a/configure.ac b/configure.ac index 27809d0..9692f24 100644 --- a/configure.ac +++ b/configure.ac @@ -168,6 +168,10 @@ AC_CHECK_HEADERS([netinet/in.h]) AC_CHECK_HEADERS([winsock2.h]) AM_CONDITIONAL(HAVE_WINSOCK2_H, test "x$HAVE_WINSOCK2_H" = "xyes") +dnl Check for FIONREAD ioctl declaration. This check is needed +dnl for the UDP plugin to build on Solaris +GST_CHECK_FIONREAD() + dnl *** checks for compiler characteristics *** dnl FIXME: check if this is used; was used for floatcast.h in base @@ -297,6 +301,12 @@ dnl Some old BSD versions and also newer OpenBSD versions : ]) ]) +dnl *** Sun Audio *** +translit(dnm, m, l) AM_CONDITIONAL(USE_SUNAUDIO, true) +GST_CHECK_FEATURE(SUNAUDIO, [Sun Audio], sunaudiosink, [ + AC_CHECK_HEADER(sys/audioio.h, HAVE_SUNAUDIO="yes", HAVE_SUNAUDIO="no") +]) + dnl *** ext plug-ins *** dnl keep this list sorted alphabetically ! @@ -597,6 +607,7 @@ ext/shout2/Makefile ext/speex/Makefile sys/Makefile sys/oss/Makefile +sys/sunaudio/Makefile po/Makefile.in gconf/Makefile gconf/gstreamer.schemas diff --git a/docs/plugins/gst-plugins-good-plugins-docs.sgml b/docs/plugins/gst-plugins-good-plugins-docs.sgml index a156d94..a469c7a 100644 --- a/docs/plugins/gst-plugins-good-plugins-docs.sgml +++ b/docs/plugins/gst-plugins-good-plugins-docs.sgml @@ -19,6 +19,8 @@ + + @@ -60,6 +62,7 @@ + diff --git a/docs/upload.mak b/docs/upload.mak index 90a86d7..b80c057 100644 --- a/docs/upload.mak +++ b/docs/upload.mak @@ -13,7 +13,7 @@ # correct User entry for the Host entry for the DOC_SERVER # these variables define the location of the online docs -DOC_SERVER=freedesktop.org +DOC_SERVER=uraeus@freedesktop.org DOC_BASE=/srv/gstreamer.freedesktop.org/www/data/doc DOC_URL=$(DOC_SERVER):$(DOC_BASE) GST_VERSION_NANO = $(GST_PLUGINS_GOOD_VERSION_NANO) diff --git a/gst-plugins-good.spec.in b/gst-plugins-good.spec.in index fba0b0c..c8e1601 100644 --- a/gst-plugins-good.spec.in +++ b/gst-plugins-good.spec.in @@ -110,6 +110,7 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/gstreamer-%{majorminor}/libgstvideomixer.so %{_libdir}/gstreamer-%{majorminor}/libgstcutter.so %{_libdir}/gstreamer-%{majorminor}/libgstmultipart.so +%{_libdir}/gstreamer-%{majorminor}/libgstid3demux.so # gstreamer-plugins with external dependencies but in the main package @USE_LIBCACA_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstcacasink.so diff --git a/sys/Makefile.am b/sys/Makefile.am index 5406c31..160ec77 100644 --- a/sys/Makefile.am +++ b/sys/Makefile.am @@ -10,6 +10,12 @@ else OSS_DIR= endif +if USE_SUNAUDIO +SUNAUDIO_DIR=sunaudio +else +SUNAUDIO_DIR= +endif + # if USE_OSX_AUDIO # OSX_AUDIO_DIR=osxaudio # else @@ -28,12 +34,6 @@ endif # QCAM_DIR= # endif -# if USE_SUNAUDIO -# SUNAUDIO_DIR=sunaudio -# else -# SUNAUDIO_DIR= -# endif - # if USE_GST_V4L2 # V4L2_DIR=v4l2 # else @@ -58,6 +58,6 @@ endif # GL_DIR= # endif -SUBDIRS=$(OSS_DIR) +SUBDIRS=$(OSS_DIR) $(SUNAUDIO_DIR) -DIST_SUBDIRS=oss +DIST_SUBDIRS=oss sunaudio diff --git a/sys/sunaudio/Makefile.am b/sys/sunaudio/Makefile.am new file mode 100644 index 0000000..95e5f9e --- /dev/null +++ b/sys/sunaudio/Makefile.am @@ -0,0 +1,21 @@ +plugin_LTLIBRARIES = libgstsunaudio.la + +libgstsunaudio_la_SOURCES = gstsunaudio.c \ + gstsunaudiosink.c \ + gstsunaudiomixerctrl.c \ + gstsunaudiomixer.c \ + gstsunaudiomixertrack.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) + +noinst_HEADERS = gstsunaudiosink.h \ + gstsunaudiomixer.h \ + gstsunaudiomixerctrl.h \ + gstsunaudiomixertrack.h + diff --git a/sys/sunaudio/gstsunaudio.c b/sys/sunaudio/gstsunaudio.c new file mode 100644 index 0000000..9cf7f7b --- /dev/null +++ b/sys/sunaudio/gstsunaudio.c @@ -0,0 +1,58 @@ +/* + * GStreamer + * Copyright (C) <2005> Brian Cameron + * + * 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" + +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)) { + return FALSE; + } + + GST_DEBUG_CATEGORY_INIT (sunaudio_debug, "sunaudio", 0, "sunaudio elements"); + +#ifdef ENABLE_NLS + setlocale (LC_ALL, ""); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); +#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..0023585 --- /dev/null +++ b/sys/sunaudio/gstsunaudiomixer.c @@ -0,0 +1,110 @@ +/* + * GStreamer + * Copyright (C) 2005 Brian Cameron + * + * 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" + +static GstElementDetails gst_sunaudiomixer_details = +GST_ELEMENT_DETAILS ("Sun Audio Mixer", + "Generic/Audio", + "Control sound input and output levels with Sun Audio", + "Brian Cameron "); + +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 (GST_ELEMENT_CLASS (klass), + &gst_sunaudiomixer_details); +} + +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 ("/dev/%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..bf585dd --- /dev/null +++ b/sys/sunaudio/gstsunaudiomixer.h @@ -0,0 +1,50 @@ +/* + * GStreamer + * Copyright (C) 2005 Brian Cameron + * + * 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(obj) (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..adceac0 --- /dev/null +++ b/sys/sunaudio/gstsunaudiomixerctrl.c @@ -0,0 +1,247 @@ +/* + * GStreamer + * Copyright (C) 2005 Brian Cameron + * + * 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 +#include +#include +#include +#include +#include +#include + +#include + +#include "gstsunaudiomixerctrl.h" +#include "gstsunaudiomixertrack.h" + +#define SCALE_FACTOR 2.55 /* 255/100 */ + +static gboolean +gst_sunaudiomixer_ctrl_open (GstSunAudioMixerCtrl * sunaudio) +{ + int fd; + + /* First try to open non-blocking */ + fd = open (sunaudio->device, O_RDWR | O_NONBLOCK); + + if (fd >= 0) { + close (fd); + fd = open (sunaudio->device, O_WRONLY); + } + + if (fd == -1) { + GST_DEBUG_OBJECT (sunaudio, + "Failed to open mixer device %s, mixing disabled: %s", sunaudio->device, + strerror (errno)); + + return FALSE; + } + + sunaudio->mixer_fd = fd; + return TRUE; +} + +void +gst_sunaudiomixer_ctrl_build_list (GstSunAudioMixerCtrl * sunaudio) +{ + GstMixerTrack *track; + + g_return_if_fail (sunaudio->mixer_fd != -1); + + track = gst_sunaudiomixer_track_new (0, 1, GST_MIXER_TRACK_OUTPUT); + sunaudio->tracklist = g_list_append (sunaudio->tracklist, track); + track = gst_sunaudiomixer_track_new (1, 1, 0); + sunaudio->tracklist = g_list_append (sunaudio->tracklist, track); + track = gst_sunaudiomixer_track_new (2, 1, 0); + sunaudio->tracklist = g_list_append (sunaudio->tracklist, track); +} + +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; + + 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); +} + +const GList * +gst_sunaudiomixer_ctrl_list_tracks (GstSunAudioMixerCtrl * mixer) +{ + gst_sunaudiomixer_ctrl_build_list (mixer); + return (const GList *) mixer->tracklist; +} + +static void +gst_sunaudiomixer_ctrl_get_volume (GstSunAudioMixerCtrl * mixer, + GstMixerTrack * track, gint * volumes) +{ + gint volume; + struct audio_info audioinfo; + GstSunAudioMixerTrack *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; + } + + switch (sunaudiotrack->track_num) { + case 0: + sunaudiotrack->vol = volumes[0] = + (audioinfo.play.gain / SCALE_FACTOR) + 0.5; + break; + case 1: + sunaudiotrack->vol = volumes[0] = + (audioinfo.record.gain / SCALE_FACTOR) + 0.5; + break; + case 2: + sunaudiotrack->vol = volumes[0] = + (audioinfo.monitor_gain / SCALE_FACTOR) + 0.5; + break; + } +} + +void +gst_sunaudiomixer_ctrl_set_volume (GstSunAudioMixerCtrl * mixer, + GstMixerTrack * track, gint * volumes) +{ + gint volume; + gchar buf[100]; + struct audio_info audioinfo; + GstSunAudioMixerTrack *sunaudiotrack = GST_SUNAUDIO_MIXER_TRACK (track); + + g_return_if_fail (mixer->mixer_fd != -1); + + volume = volumes[0] * SCALE_FACTOR + 0.5; + + /* Set the volume */ + AUDIO_INITINFO (&audioinfo); + + switch (sunaudiotrack->track_num) { + case 0: + audioinfo.play.gain = volume; + break; + case 1: + audioinfo.record.gain = volume; + break; + case 2: + audioinfo.monitor_gain = volume; + break; + } + + if (ioctl (mixer->mixer_fd, AUDIO_SETINFO, &audioinfo) < 0) { + g_warning ("Error setting audio device volume"); + return; + } + + sunaudiotrack->vol = volume; +} + +static void +gst_sunaudiomixer_ctrl_set_mute (GstSunAudioMixerCtrl * sunaudio, + GstMixerTrack * track, gboolean mute) +{ + struct audio_info audioinfo; + GstSunAudioMixerTrack *sunaudiotrack = GST_SUNAUDIO_MIXER_TRACK (track); + gint volume; + + g_return_if_fail (sunaudio->mixer_fd != -1); + if (sunaudiotrack->track_num != 0) + return; + + AUDIO_INITINFO (&audioinfo); + + if (mute) { + audioinfo.output_muted = 1; + volume = 0; + } else { + audioinfo.output_muted = 0; + volume = sunaudiotrack->vol; + } + + switch (sunaudiotrack->track_num) { + case 0: + audioinfo.play.gain = volume; + break; + case 1: + audioinfo.record.gain = volume; + break; + case 2: + audioinfo.monitor_gain = volume; + break; + } + + if (ioctl (sunaudio->mixer_fd, AUDIO_SETINFO, &audioinfo) < 0) { + g_warning ("Error setting audio device volume"); + return; + } +} + +static void +gst_sunaudiomixer_ctrl_set_record (GstSunAudioMixerCtrl * mixer, + GstMixerTrack * track, gboolean record) +{ + /* Implementation Pending */ +} diff --git a/sys/sunaudio/gstsunaudiomixerctrl.h b/sys/sunaudio/gstsunaudiomixerctrl.h new file mode 100644 index 0000000..19d93ab --- /dev/null +++ b/sys/sunaudio/gstsunaudiomixerctrl.h @@ -0,0 +1,142 @@ +/* SunAudio mixer interface element. + * Copyright (C) 2005 Brian Cameron + * + * 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 + +#include +#include + +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); + +#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 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 diff --git a/sys/sunaudio/gstsunaudiomixertrack.c b/sys/sunaudio/gstsunaudiomixertrack.c new file mode 100644 index 0000000..f6a4dc1 --- /dev/null +++ b/sys/sunaudio/gstsunaudiomixertrack.c @@ -0,0 +1,109 @@ +/* + * GStreamer + * Copyright (C) 2005 Brian Cameron + * + * 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 +#include +#include +#include +#include +#include +#include + +#include + +#include "gstsunaudiomixertrack.h" + +#define MIXER_DEVICES 3 +#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->vol = 0; + track->track_num = 0; +} + +static const gchar **labels = NULL; + +static void +fill_labels (void) +{ + int i; + struct + { + gchar *given, *wanted; + } + cases[] = { + { + "Vol ", N_("Volume")} + , { + "Gain ", N_("Gain")} + , { + "Mon ", N_("Monitor")} + , { + NULL, NULL} + }; + + labels = g_malloc (sizeof (gchar *) * MIXER_DEVICES); + + for (i = 0; i < MIXER_DEVICES; i++) { + labels[i] = g_strdup (cases[i].wanted); + } +} + +GstMixerTrack * +gst_sunaudiomixer_track_new (gint track_num, gint max_chans, gint flags) +{ + GstSunAudioMixerTrack *sunaudiotrack; + GstMixerTrack *track; + gint volume; + + if (!labels) + fill_labels (); + + sunaudiotrack = g_object_new (GST_TYPE_SUNAUDIO_MIXER_TRACK, NULL); + track = GST_MIXER_TRACK (sunaudiotrack); + track->label = g_strdup (labels[track_num]); + track->num_channels = max_chans; + track->flags = flags; + track->min_volume = 0; + track->max_volume = 100; + sunaudiotrack->track_num = track_num; + + sunaudiotrack->vol = (0 & 0xff); + + return track; +} diff --git a/sys/sunaudio/gstsunaudiomixertrack.h b/sys/sunaudio/gstsunaudiomixertrack.h new file mode 100644 index 0000000..aaf1e06 --- /dev/null +++ b/sys/sunaudio/gstsunaudiomixertrack.h @@ -0,0 +1,59 @@ +/* GStreamer SunAudio Mixer implementation + * Copyright (C) 2005 Brian Cameron + * + * 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 +#include + +G_BEGIN_DECLS + +#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 vol; + gint track_num; +} GstSunAudioMixerTrack; + +typedef struct _GstSunAudioMixerTrackClass { + GstMixerTrackClass parent; +} GstSunAudioMixerTrackClass; + +GType gst_sunaudiomixer_track_get_type (void); +GstMixerTrack* gst_sunaudiomixer_track_new (gint track_num, gint max_chans, gint flags); + +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..9ddf0a2 --- /dev/null +++ b/sys/sunaudio/gstsunaudiosink.c @@ -0,0 +1,411 @@ +/* + * GStreamer + * Copyright (C) 2004 David A. Schleef + * Copyright (C) 2005 Brian Cameron + * + * 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. + * + * Example launch line + * + * + * gst-launch -v sinesrc ! sunaudiosink + * + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "gstsunaudiosink.h" + +/* elementfactory information */ +static GstElementDetails plugin_details = GST_ELEMENT_DETAILS ("Sun Audio Sink", + "Sink/Audio", + "Audio sink for Sun Audio devices", + "David A. Schleef , " + "Brian Cameron "); + +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_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_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_sunaudiosink_factory)); + gst_element_class_set_details (element_class, &plugin_details); +} + +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_ref (GST_TYPE_BASE_AUDIO_SINK); + + gobject_class->dispose = gst_sunaudiosink_dispose; + gobject_class->set_property = + GST_DEBUG_FUNCPTR (gst_sunaudiosink_set_property); + gobject_class->get_property = + GST_DEBUG_FUNCPTR (gst_sunaudiosink_get_property); + + g_object_class_install_property (gobject_class, PROP_DEVICE, + g_param_spec_string ("device", "Device", "Audio Device (/dev/audio)", + DEFAULT_DEVICE, G_PARAM_READWRITE)); + + 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); +} + +static void +gst_sunaudiosink_init (GstSunAudioSink * sunaudiosink) +{ + const char *audiodev; + GstClockTime buffer_time; + GValue gvalue = { 0, }; + + GST_DEBUG_OBJECT (sunaudiosink, "initializing sunaudiosink"); + + /* + * According to the Sun audio man page, this value can't be set and + * will be ignored for playback, but setting it the same way that + * esound does. Probably not necessary, but doesn't hurt. + */ + sunaudiosink->buffer_size = 8180; + + /* + * Reset the buffer-time to 3ms instead of the normal default of 500us + * (6 times larger, in other words). + * + * Setting a larger buffer causes the sinesrc to not stutter with this + * sink. The fact that SunAudio requires a larger buffer should be + * investigated further to see if this is needed due to limitations of + * SunAudio itself or because of a more serious problem with the + * GStreamer engine on Solaris. + */ + g_value_init (&gvalue, G_TYPE_INT64); + g_object_get_property (G_OBJECT (sunaudiosink), "buffer-time", &gvalue); + buffer_time = g_value_get_int64 (&gvalue); + if (buffer_time < 3000000) { + g_value_set_int64 (&gvalue, 3000000); + g_object_set_property (G_OBJECT (sunaudiosink), "buffer-time", &gvalue); + } + + audiodev = g_getenv ("AUDIODEV"); + if (audiodev == NULL) + audiodev = DEFAULT_DEVICE; + sunaudiosink->device = g_strdup (audiodev); +} + +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: + g_free (sunaudiosink->device); + sunaudiosink->device = g_strdup (g_value_get_string (value)); + 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: + g_value_set_string (value, sunaudiosink->device); + 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 */ + fd = open (sunaudiosink->device, O_WRONLY | O_NONBLOCK); + + if (fd >= 0) { + close (fd); + fd = open (sunaudiosink->device, O_WRONLY); + } + + if (fd == -1) { + GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, OPEN_WRITE, (NULL), + ("can't open connection to Sun Audio device %s", sunaudiosink->device)); + + return FALSE; + } + + sunaudiosink->fd = fd; + + ret = ioctl (fd, AUDIO_GETDEV, &sunaudiosink->dev); + if (ret == -1) { + GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s", + strerror (errno))); + return FALSE; + } + + 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) { + GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s", + strerror (errno))); + return FALSE; + } + + 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; +} + +static gboolean +gst_sunaudiosink_close (GstAudioSink * asink) +{ + GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (asink); + + 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; + if (!(ports & AUDIO_SPEAKER) && (ainfo.play.avail_ports & AUDIO_SPEAKER)) { + ports = ports | AUDIO_SPEAKER; + } + + 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; + ainfo.play.buffer_size = sunaudiosink->buffer_size; + ainfo.output_muted = 0; + + ret = ioctl (sunaudiosink->fd, AUDIO_SETINFO, &ainfo); + if (ret == -1) { + GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s", + strerror (errno))); + return FALSE; + } + + return TRUE; +} + +static gboolean +gst_sunaudiosink_unprepare (GstAudioSink * asink) +{ + return TRUE; +} + +static guint +gst_sunaudiosink_write (GstAudioSink * asink, gpointer data, guint length) +{ + GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (asink); + + if (length > sunaudiosink->buffer_size) + return write (sunaudiosink->fd, data, sunaudiosink->buffer_size); + else + return write (sunaudiosink->fd, data, length); +} + +/* + * Should provide the current delay between writing a sample to the + * audio device and that sample being actually played. Returning 0 for + * now, but this isn't good for synchronization + */ +static guint +gst_sunaudiosink_delay (GstAudioSink * asink) +{ + return 0; +} + +static void +gst_sunaudiosink_reset (GstAudioSink * asink) +{ +} diff --git a/sys/sunaudio/gstsunaudiosink.h b/sys/sunaudio/gstsunaudiosink.h new file mode 100644 index 0000000..0b59430 --- /dev/null +++ b/sys/sunaudio/gstsunaudiosink.h @@ -0,0 +1,63 @@ +/* GStreamer + * Copyright (C) 2004 David A. Schleef + * Copyright (C) 2005 Brian Cameron + * + * 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 +#include +#include + +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(obj) (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; + + gint bytes_per_sample; + gint buffer_size; +}; + +struct _GstSunAudioSinkClass { + GstAudioSinkClass parent_class; +}; + +GType gst_sunaudiosink_get_type(void); + +G_END_DECLS + +#endif /* __GST_SUNAUDIO_SINK_H__ */ + -- 2.7.4