pkgsrc-Changes archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
CVS commit: pkgsrc/audio/portaudio
Module Name: pkgsrc
Committed By: nia
Date: Fri Apr 17 15:50:03 UTC 2020
Modified Files:
pkgsrc/audio/portaudio: Makefile buildlink3.mk distinfo
pkgsrc/audio/portaudio/patches: patch-include_pa__unix__oss.h
patch-include_portaudio.h patch-src_hostapi_alsa_pa__linux__alsa.c
Added Files:
pkgsrc/audio/portaudio/patches: patch-Makefile.in
patch-bindings_cpp_Makefile.am patch-configure.in
patch-src_hostapi_sun_pa__unix__sun.c
patch-src_os_unix_pa__unix__hostapis.c
Removed Files:
pkgsrc/audio/portaudio/patches: patch-configure
Log Message:
portaudio: Add a Sun/NetBSD audio backend. This works with Audacity.
While here, generally clean up the package...
Bump PKGREVISION
To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.30 pkgsrc/audio/portaudio/Makefile
cvs rdiff -u -r1.14 -r1.15 pkgsrc/audio/portaudio/buildlink3.mk
cvs rdiff -u -r1.21 -r1.22 pkgsrc/audio/portaudio/distinfo
cvs rdiff -u -r0 -r1.1 pkgsrc/audio/portaudio/patches/patch-Makefile.in \
pkgsrc/audio/portaudio/patches/patch-bindings_cpp_Makefile.am \
pkgsrc/audio/portaudio/patches/patch-configure.in \
pkgsrc/audio/portaudio/patches/patch-src_hostapi_sun_pa__unix__sun.c \
pkgsrc/audio/portaudio/patches/patch-src_os_unix_pa__unix__hostapis.c
cvs rdiff -u -r1.1 -r0 pkgsrc/audio/portaudio/patches/patch-configure
cvs rdiff -u -r1.1 -r1.2 \
pkgsrc/audio/portaudio/patches/patch-include_pa__unix__oss.h \
pkgsrc/audio/portaudio/patches/patch-include_portaudio.h
cvs rdiff -u -r1.2 -r1.3 \
pkgsrc/audio/portaudio/patches/patch-src_hostapi_alsa_pa__linux__alsa.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: pkgsrc/audio/portaudio/Makefile
diff -u pkgsrc/audio/portaudio/Makefile:1.29 pkgsrc/audio/portaudio/Makefile:1.30
--- pkgsrc/audio/portaudio/Makefile:1.29 Wed Apr 15 17:12:14 2020
+++ pkgsrc/audio/portaudio/Makefile Fri Apr 17 15:50:03 2020
@@ -1,8 +1,8 @@
-# $NetBSD: Makefile,v 1.29 2020/04/15 17:12:14 nia Exp $
+# $NetBSD: Makefile,v 1.30 2020/04/17 15:50:03 nia Exp $
DISTNAME= pa_stable_v190600_20161030
PKGNAME= ${DISTNAME:S/^pa_stable_v/portaudio-/1:S/_/./g}
-PKGREVISION= 3
+PKGREVISION= 5
CATEGORIES= audio
MASTER_SITES= http://www.portaudio.com/archives/
EXTRACT_SUFX= .tgz
@@ -15,7 +15,9 @@ LICENSE= mit
CONFLICTS+= portaudio-devel-[0-9]*
SUPERSEDES+= portaudio-devel-[0-9]*
+WRKSRC= ${WRKDIR}/portaudio
USE_LANGUAGES= c c++
+USE_TOOLS+= autoconf autoreconf automake
USE_TOOLS+= gmake pkg-config
USE_LIBTOOL= yes
GNU_CONFIGURE= yes
@@ -23,41 +25,26 @@ GNU_CONFIGURE= yes
# No rule to make target '../../../lib/libportaudio.la', needed by 'libportaudiocpp.la'. Stop.
MAKE_JOBS_SAFE= no
-GNU_CONFIGURE_LIBSUBDIR= portaudio2
+.include "../../mk/oss.buildlink3.mk"
-NOT_FOR_PLATFORM= Interix-*-*
+PLIST_VARS+= oss
+.if ${OSS_TYPE} != "none"
+PLIST.oss= yes
+.endif
+
+GNU_CONFIGURE_LIBSUBDIR= portaudio2
CONFIGURE_ARGS+= --enable-cxx
CONFIGURE_ARGS+= --includedir=${PREFIX}/include/portaudio2
CONFIGURE_ARGS+= --disable-mac-universal
-.include "../../mk/oss.buildlink3.mk"
-PLIST_VARS+= oss
-.if ${OSS_TYPE} != "none"
-PLIST.oss= yes
-LDFLAGS+= ${LIBOSSAUDIO}
-.endif
-
PKGCONFIG_OVERRIDE= portaudio-2.0.pc.in
-WRKSRC= ${WRKDIR}/portaudio
-
-INSTALLATION_DIRS= include/portaudio2 lib/portaudio2 lib/pkgconfig
-
-SUBST_CLASSES+= pthread
-SUBST_STAGE.pthread= pre-configure
-SUBST_MESSAGE.pthread= Fixing -lpthread references.
-SUBST_FILES.pthread= configure
-SUBST_SED.pthread= -e 's/-D_REENTRANT/${PTHREAD_CFLAGS}/g'
-SUBST_SED.pthread+= -e 's/-lpthread/${PTHREAD_LDFLAGS} ${PTHREAD_LIBS}/g'
-
-SUBST_CLASSES+= pc
-SUBST_STAGE.pc= pre-configure
-SUBST_MESSAGE.pc= Fixing pkgconfig directory
-SUBST_FILES.pc= Makefile.in bindings/cpp/Makefile.in
-SUBST_SED.pc= -e 's/$$(libdir)\/pkgconfig/$$(prefix)\/lib\/pkgconfig/g'
CFLAGS.Darwin+= -Wno-deprecated-declarations
+pre-configure:
+ cd ${WRKSRC} && autoreconf -i
+
.include "options.mk"
.include "../../mk/pthread.buildlink3.mk"
.include "../../mk/bsd.pkg.mk"
Index: pkgsrc/audio/portaudio/buildlink3.mk
diff -u pkgsrc/audio/portaudio/buildlink3.mk:1.14 pkgsrc/audio/portaudio/buildlink3.mk:1.15
--- pkgsrc/audio/portaudio/buildlink3.mk:1.14 Sun Dec 22 04:14:33 2019
+++ pkgsrc/audio/portaudio/buildlink3.mk Fri Apr 17 15:50:03 2020
@@ -1,4 +1,4 @@
-# $NetBSD: buildlink3.mk,v 1.14 2019/12/22 04:14:33 nia Exp $
+# $NetBSD: buildlink3.mk,v 1.15 2020/04/17 15:50:03 nia Exp $
BUILDLINK_TREE+= portaudio
@@ -15,11 +15,11 @@ pkgbase:= portaudio
.include "../../mk/pkg-build-options.mk"
-.if !empty(PKG_BUILD_OPTIONS.portaudio:Malsa)
+.if ${PKG_BUILD_OPTIONS.portaudio:Malsa}
. include "../../audio/alsa-lib/buildlink3.mk"
.endif
-.if !empty(PKG_BUILD_OPTIONS.portaudio:Mjack)
+.if ${PKG_BUILD_OPTIONS.portaudio:Mjack}
. include "../../audio/jack/buildlink3.mk"
.endif
.endif # PORTAUDIO_BUILDLINK3_MK
Index: pkgsrc/audio/portaudio/distinfo
diff -u pkgsrc/audio/portaudio/distinfo:1.21 pkgsrc/audio/portaudio/distinfo:1.22
--- pkgsrc/audio/portaudio/distinfo:1.21 Wed Apr 15 17:12:14 2020
+++ pkgsrc/audio/portaudio/distinfo Fri Apr 17 15:50:03 2020
@@ -1,14 +1,18 @@
-$NetBSD: distinfo,v 1.21 2020/04/15 17:12:14 nia Exp $
+$NetBSD: distinfo,v 1.22 2020/04/17 15:50:03 nia Exp $
SHA1 (pa_stable_v190600_20161030.tgz) = 56c596bba820d90df7d057d8f6a0ec6bf9ab82e8
RMD160 (pa_stable_v190600_20161030.tgz) = e6e5cd3f3cb7469aa17549c189e445d573567e13
SHA512 (pa_stable_v190600_20161030.tgz) = 7ec692cbd8c23878b029fad9d9fd63a021f57e60c4921f602995a2fca070c29f17a280c7f2da5966c4aad29d28434538452f4c822eacf3a60af59a6dc8e9704c
Size (pa_stable_v190600_20161030.tgz) = 1450572 bytes
-SHA1 (patch-configure) = 6db6442804f44ddadddd91252d1c7c66dc812d6a
-SHA1 (patch-include_pa__unix__oss.h) = 55213cf8dfa4f81b8be23c912deddd8cc8b8117f
-SHA1 (patch-include_portaudio.h) = fc5ea598b2e6fc80a0e106a400ffab521ea3cf4e
+SHA1 (patch-Makefile.in) = 28f587f171b4a504e3982e6f8fcf3f148e5aa5c9
+SHA1 (patch-bindings_cpp_Makefile.am) = bcd45cba537c867ed9b2e20e1468e9f16ed0b3f7
+SHA1 (patch-configure.in) = 4241ddc620e50364aa86fe583a6d8709fdf833ee
+SHA1 (patch-include_pa__unix__oss.h) = 8e4ede09d5bf730bf8c2e8ca4aca6f700f58f2f7
+SHA1 (patch-include_portaudio.h) = 9a2e4aeb126056aded5cc49c40cde40e16738757
SHA1 (patch-src_common_pa__front.c) = cdddb6f537f803b55873ad6bfa936a6bff47556d
SHA1 (patch-src_common_pa__stream.c) = 58e6ab2a61957208973a59be2f1140abc922f360
SHA1 (patch-src_common_pa__stream.h) = 94781a9ae79ea1340eea8caadc106416c019cf74
-SHA1 (patch-src_hostapi_alsa_pa__linux__alsa.c) = 6ddbeca36be30153f9c6c316c2fb78c06bbbf05d
+SHA1 (patch-src_hostapi_alsa_pa__linux__alsa.c) = 71daf913422f72aa379ae8cc302186800cff7717
SHA1 (patch-src_hostapi_oss_pa__unix__oss.c) = 572c48f64104e22e7ae49acc54a26e549e381b5b
+SHA1 (patch-src_hostapi_sun_pa__unix__sun.c) = ce11c0720285ca850865555fdb21dc0ad803b86b
+SHA1 (patch-src_os_unix_pa__unix__hostapis.c) = 8cfc7d7aac8f9803e204711ded3d64842913f4fd
Index: pkgsrc/audio/portaudio/patches/patch-include_pa__unix__oss.h
diff -u pkgsrc/audio/portaudio/patches/patch-include_pa__unix__oss.h:1.1 pkgsrc/audio/portaudio/patches/patch-include_pa__unix__oss.h:1.2
--- pkgsrc/audio/portaudio/patches/patch-include_pa__unix__oss.h:1.1 Sat Oct 26 17:22:39 2019
+++ pkgsrc/audio/portaudio/patches/patch-include_pa__unix__oss.h Fri Apr 17 15:50:03 2020
@@ -1,62 +1,10 @@
-$NetBSD: patch-include_pa__unix__oss.h,v 1.1 2019/10/26 17:22:39 nia Exp $
+$NetBSD: patch-include_pa__unix__oss.h,v 1.2 2020/04/17 15:50:03 nia Exp $
Add features needed to make portmixer work in audacity.
---- /dev/null
+--- include/pa_unix_oss.h.orig 2020-04-15 17:02:57.772786926 +0000
+++ include/pa_unix_oss.h
-@@ -0,0 +1,104 @@
-+#ifndef PA_UNIX_OSS_H
-+#define PA_UNIX_OSS_H
-+
-+/*
-+ *
-+ * PortAudio Portable Real-Time Audio Library
-+ * OSS-specific extensions
-+ *
-+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
-+ *
-+ * 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.
-+ *
-+ * Any person wishing to distribute modifications to the Software is
-+ * requested to send the modifications to the original developer so that
-+ * they can be incorporated into the canonical version.
-+ *
-+ * 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.
-+ *
-+ */
-+
-+/** @file
-+ * OSS-specific PortAudio API extension header file.
-+ */
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+const char *PaOSS_GetStreamInputDevice( PaStream *s );
-+
-+const char *PaOSS_GetStreamOutputDevice( PaStream *s );
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif
+@@ -0,0 +1,52 @@
+#ifndef PA_UNIX_OSS_H
+#define PA_UNIX_OSS_H
+
Index: pkgsrc/audio/portaudio/patches/patch-include_portaudio.h
diff -u pkgsrc/audio/portaudio/patches/patch-include_portaudio.h:1.1 pkgsrc/audio/portaudio/patches/patch-include_portaudio.h:1.2
--- pkgsrc/audio/portaudio/patches/patch-include_portaudio.h:1.1 Sat Oct 26 17:22:39 2019
+++ pkgsrc/audio/portaudio/patches/patch-include_portaudio.h Fri Apr 17 15:50:03 2020
@@ -1,6 +1,7 @@
-$NetBSD: patch-include_portaudio.h,v 1.1 2019/10/26 17:22:39 nia Exp $
+$NetBSD: patch-include_portaudio.h,v 1.2 2020/04/17 15:50:03 nia Exp $
-Add features needed to make portmixer work in audacity.
+- Sun/NetBSD audio support.
+- Add features needed to make portmixer work in audacity.
--- include/portaudio.h.orig 2016-10-30 01:23:04.000000000 +0000
+++ include/portaudio.h
Index: pkgsrc/audio/portaudio/patches/patch-src_hostapi_alsa_pa__linux__alsa.c
diff -u pkgsrc/audio/portaudio/patches/patch-src_hostapi_alsa_pa__linux__alsa.c:1.2 pkgsrc/audio/portaudio/patches/patch-src_hostapi_alsa_pa__linux__alsa.c:1.3
--- pkgsrc/audio/portaudio/patches/patch-src_hostapi_alsa_pa__linux__alsa.c:1.2 Sat Oct 26 17:22:08 2019
+++ pkgsrc/audio/portaudio/patches/patch-src_hostapi_alsa_pa__linux__alsa.c Fri Apr 17 15:50:03 2020
@@ -1,8 +1,7 @@
-$NetBSD: patch-src_hostapi_alsa_pa__linux__alsa.c,v 1.2 2019/10/26 17:22:08 nia Exp $
+$NetBSD: patch-src_hostapi_alsa_pa__linux__alsa.c,v 1.3 2020/04/17 15:50:03 nia Exp $
-Support building on non-Linux systems.
-
-Add features needed to make portmixer work with audacity.
+- Support building on non-Linux systems.
+- Add features needed to make portmixer work with audacity.
--- src/hostapi/alsa/pa_linux_alsa.c.orig 2016-10-30 01:23:04.000000000 +0000
+++ src/hostapi/alsa/pa_linux_alsa.c
Added files:
Index: pkgsrc/audio/portaudio/patches/patch-Makefile.in
diff -u /dev/null pkgsrc/audio/portaudio/patches/patch-Makefile.in:1.1
--- /dev/null Fri Apr 17 15:50:03 2020
+++ pkgsrc/audio/portaudio/patches/patch-Makefile.in Fri Apr 17 15:50:03 2020
@@ -0,0 +1,26 @@
+$NetBSD: patch-Makefile.in,v 1.1 2020/04/17 15:50:03 nia Exp $
+
+- Sun/NetBSD audio support.
+- Correct path for pkgconfig files.
+
+--- Makefile.in.orig 2016-10-30 01:23:04.000000000 +0000
++++ Makefile.in
+@@ -146,6 +146,7 @@ SRC_DIRS = \
+ src/hostapi/dsound \
+ src/hostapi/jack \
+ src/hostapi/oss \
++ src/hostapi/sun \
+ src/hostapi/wasapi \
+ src/hostapi/wdmks \
+ src/hostapi/wmme \
+@@ -193,8 +194,8 @@ install: lib/$(PALIB) portaudio-2.0.pc
+ for include in $(INCLUDES); do \
+ $(INSTALL_DATA) -m 644 $(top_srcdir)/include/$$include $(DESTDIR)$(includedir)/$$include; \
+ done
+- $(INSTALL) -d $(DESTDIR)$(libdir)/pkgconfig
+- $(INSTALL) -m 644 portaudio-2.0.pc $(DESTDIR)$(libdir)/pkgconfig/portaudio-2.0.pc
++ $(INSTALL) -d $(DESTDIR)$(prefix)/lib/pkgconfig
++ $(INSTALL) -m 644 portaudio-2.0.pc $(DESTDIR)$(prefix)/lib/pkgconfig/portaudio-2.0.pc
+ @echo ""
+ @echo "------------------------------------------------------------"
+ @echo "PortAudio was successfully installed."
Index: pkgsrc/audio/portaudio/patches/patch-bindings_cpp_Makefile.am
diff -u /dev/null pkgsrc/audio/portaudio/patches/patch-bindings_cpp_Makefile.am:1.1
--- /dev/null Fri Apr 17 15:50:03 2020
+++ pkgsrc/audio/portaudio/patches/patch-bindings_cpp_Makefile.am Fri Apr 17 15:50:03 2020
@@ -0,0 +1,13 @@
+$NetBSD: patch-bindings_cpp_Makefile.am,v 1.1 2020/04/17 15:50:03 nia Exp $
+
+Correct path for pkgconfig files.
+
+--- bindings/cpp/Makefile.am.orig 2016-10-30 01:23:04.000000000 +0000
++++ bindings/cpp/Makefile.am
+@@ -3,5 +3,5 @@ SUBDIRS = lib include bin
+
+ EXTRA_DIST = portaudiocpp.pc
+
+-pkgconfigdir = $(libdir)/pkgconfig
++pkgconfigdir = $(prefix)/lib/pkgconfig
+ pkgconfig_DATA = portaudiocpp.pc
Index: pkgsrc/audio/portaudio/patches/patch-configure.in
diff -u /dev/null pkgsrc/audio/portaudio/patches/patch-configure.in:1.1
--- /dev/null Fri Apr 17 15:50:03 2020
+++ pkgsrc/audio/portaudio/patches/patch-configure.in Fri Apr 17 15:50:03 2020
@@ -0,0 +1,69 @@
+$NetBSD: patch-configure.in,v 1.1 2020/04/17 15:50:03 nia Exp $
+
+- Sun/NetBSD audio support
+- Install extra headers needed by portmixer in Audacity for OSS.
+- Don't use -pthread
+
+--- configure.in.orig 2016-10-30 01:23:04.000000000 +0000
++++ configure.in
+@@ -32,6 +32,10 @@ AC_ARG_WITH(oss,
+ AS_HELP_STRING([--with-oss], [Enable support for OSS @<:@autodetect@:>@]),
+ [with_oss=$withval])
+
++AC_ARG_WITH(sun,
++ AS_HELP_STRING([--with-sun], [Enable support for Sun/NetBSD Audio @<:@autodetect@:>@]),
++ [with_sun=$withval])
++
+ AC_ARG_WITH(asihpi,
+ AS_HELP_STRING([--with-asihpi], [Enable support for ASIHPI @<:@autodetect@:>@]),
+ [with_asihpi=$withval])
+@@ -132,6 +136,10 @@ if test "x$with_oss" != "xno"; then
+ AC_CHECK_LIB(ossaudio, _oss_ioctl, have_libossaudio=yes, have_libossaudio=no)
+ fi
+ fi
++have_sun=no
++if test "x$with_sun" != "xno"; then
++ AC_CHECK_HEADERS([sys/audioio.h], [have_sun=yes])
++fi
+ have_jack=no
+ if test "x$with_jack" != "xno"; then
+ PKG_CHECK_MODULES(JACK, jack, have_jack=yes, have_jack=no)
+@@ -416,6 +424,7 @@ case "${host_os}" in
+
+ if [[ "$with_oss" != "no" ]] ; then
+ OTHER_OBJS="$OTHER_OBJS src/hostapi/oss/pa_unix_oss.o"
++ INCLUDES="$INCLUDES pa_unix_oss.h"
+ if [[ "$have_libossaudio" = "yes" ]] ; then
+ DLL_LIBS="$DLL_LIBS -lossaudio"
+ LIBS="$LIBS -lossaudio"
+@@ -423,6 +432,11 @@ case "${host_os}" in
+ AC_DEFINE(PA_USE_OSS,1)
+ fi
+
++ if [[ "$with_sun" != "no" ]] ; then
++ OTHER_OBJS="$OTHER_OBJS src/hostapi/sun/pa_unix_sun.o"
++ AC_DEFINE(PA_USE_SUN,1)
++ fi
++
+ if [[ "$have_asihpi" = "yes" ] && [ "$with_asihpi" != "no" ]] ; then
+ LIBS="$LIBS -lhpi"
+ DLL_LIBS="$DLL_LIBS -lhpi"
+@@ -430,8 +444,8 @@ case "${host_os}" in
+ AC_DEFINE(PA_USE_ASIHPI,1)
+ fi
+
+- DLL_LIBS="$DLL_LIBS -lm -lpthread"
+- LIBS="$LIBS -lm -lpthread"
++ DLL_LIBS="$DLL_LIBS -lm ${PTHREAD_LDFLAGS} ${PTHREAD_LIBS}"
++ LIBS="$LIBS -lm ${PTHREAD_LDFLAGS} ${PTHREAD_LIBS}"
+ PADLL="libportaudio.so"
+
+ ## support sun cc compiler flags
+@@ -510,6 +524,7 @@ case "$target_os" in
+ *)
+ AC_MSG_RESULT([
+ OSS ......................... $have_oss
++ Sun ......................... $have_sun
+ JACK ........................ $have_jack
+ ])
+ ;;
Index: pkgsrc/audio/portaudio/patches/patch-src_hostapi_sun_pa__unix__sun.c
diff -u /dev/null pkgsrc/audio/portaudio/patches/patch-src_hostapi_sun_pa__unix__sun.c:1.1
--- /dev/null Fri Apr 17 15:50:03 2020
+++ pkgsrc/audio/portaudio/patches/patch-src_hostapi_sun_pa__unix__sun.c Fri Apr 17 15:50:03 2020
@@ -0,0 +1,1144 @@
+$NetBSD: patch-src_hostapi_sun_pa__unix__sun.c,v 1.1 2020/04/17 15:50:03 nia Exp $
+
+Sun/NetBSD audio support.
+
+--- src/hostapi/sun/pa_unix_sun.c.orig 2020-04-17 15:03:32.627418402 +0000
++++ src/hostapi/sun/pa_unix_sun.c
+@@ -0,0 +1,1137 @@
++/*
++ * $Id"
++ * PortAudio Portable Real-Time Audio Library
++ * Latest Version at: http://www.portaudio.com
++ * Sun implementation by:
++ * Nia Alarie
++ *
++ * Based on the Open Source API proposed by Ross Bencina
++ * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
++ *
++ * 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.
++ */
++
++/*
++ * The text above constitutes the entire PortAudio license; however,
++ * the PortAudio community also makes the following non-binding requests:
++ *
++ * Any person wishing to distribute modifications to the Software is
++ * requested to send the modifications to the original developer so that
++ * they can be incorporated into the canonical version. It is also
++ * requested that these non-binding requests be included along with the
++ * license above.
++ */
++
++/** @file
++ @ingroup hostapi_src
++*/
++
++#include <sys/audioio.h>
++#include <sys/ioctl.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <pthread.h>
++#include <poll.h>
++
++#include <string.h>
++#include <stdbool.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <math.h>
++
++#include "pa_util.h"
++#include "pa_unix_util.h"
++#include "pa_debugprint.h"
++#include "pa_allocation.h"
++#include "pa_hostapi.h"
++#include "pa_stream.h"
++#include "pa_cpuload.h"
++#include "pa_process.h"
++
++#ifndef SUN_MAX_DEVICES
++#define SUN_MAX_DEVICES (32)
++#endif
++
++#ifndef SUN_DEFAULT_FRAMES
++#define SUN_DEFAULT_FRAMES (128)
++#endif
++
++#ifndef SUN_DEFAULT_MAX_CHANNELS
++# ifdef __NetBSD__
++# define SUN_DEFAULT_MAX_CHANNELS (12)
++# else
++# define SUN_DEFAULT_MAX_CHANNELS (2)
++# endif
++#endif
++
++#ifndef SUN_DEV_PREFIX
++# ifdef __sun
++# define SUN_DEV_PREFIX "/dev/sound/"
++# else
++# define SUN_DEV_PREFIX "/dev/audio"
++# endif
++#endif
++
++#ifndef SUN_DEV_DEFAULT
++#define SUN_DEV_DEFAULT "/dev/audio"
++#endif
++
++#ifndef AUDIO_FLUSH
++#define AUDIO_FLUSH I_FLUSH
++#endif
++
++#ifndef AUDIO_ENCODING_SLINEAR
++#define AUDIO_ENCODING_SLINEAR AUDIO_ENCODING_LINEAR
++#endif
++
++#if 0
++/* testing */
++#undef AUDIO_GETPROPS
++#undef AUDIO_GETFORMAT
++#undef AUDIO_GETBUFINFO
++#endif
++
++PaError PaSun_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
++static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
++static bool AttemptEncoding( int fd, int encoding, int precision, bool record );
++static PaSampleFormat GetSupportedEncodings( int fd, bool record );
++static PaError PaFormatToSunFormat( PaSampleFormat fmt, struct audio_prinfo *info );
++static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
++ const PaStreamParameters *inputParameters,
++ const PaStreamParameters *outputParameters,
++ double sampleRate );
++static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
++ PaStream** s,
++ const PaStreamParameters *inputParameters,
++ const PaStreamParameters *outputParameters,
++ double sampleRate,
++ unsigned long framesPerBuffer,
++ PaStreamFlags streamFlags,
++ PaStreamCallback *streamCallback,
++ void *userData );
++static PaError CloseStream( PaStream* stream );
++static PaError StartStream( PaStream *stream );
++static PaError StopStream( PaStream *stream );
++static PaError AbortStream( PaStream *stream );
++static PaError IsStreamStopped( PaStream *s );
++static PaError IsStreamActive( PaStream *stream );
++static PaTime GetStreamTime( PaStream *stream );
++static double GetStreamCpuLoad( PaStream* stream );
++static PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames );
++static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames );
++static signed long GetStreamReadAvailable( PaStream* stream );
++static signed long GetStreamWriteAvailable( PaStream* stream );
++
++/* PaSunHostApiRepresentation - host api datastructure specific to this implementation */
++
++typedef struct
++{
++ PaUtilHostApiRepresentation inheritedHostApiRep;
++ PaUtilStreamInterface callbackStreamInterface;
++ PaUtilStreamInterface blockingStreamInterface;
++ PaUtilAllocationGroup *allocations;
++}
++PaSunHostApiRepresentation;
++
++
++PaError PaSun_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
++{
++ PaError result = paNoError;
++ int fd = -1, i, deviceCount = 0;
++ PaSunHostApiRepresentation *sunHostApi;
++ PaUtilHostApiRepresentation *common;
++
++ PA_UNLESS( sunHostApi = calloc(1, sizeof(PaSunHostApiRepresentation)), paInsufficientMemory );
++
++ common = &sunHostApi->inheritedHostApiRep;
++ common->info.structVersion = 1;
++ common->info.type = paInDevelopment;
++ common->info.name = "Sun AudioIO";
++
++ common->Terminate = Terminate;
++ common->OpenStream = OpenStream;
++ common->IsFormatSupported = IsFormatSupported;
++
++ common->info.defaultInputDevice =
++ common->info.defaultOutputDevice = paNoDevice;
++
++ PA_UNLESS( sunHostApi->allocations = PaUtil_CreateAllocationGroup(), paInsufficientMemory );
++
++ if( (common->deviceInfos = PaUtil_GroupAllocateMemory(
++ sunHostApi->allocations, sizeof(PaDeviceInfo *) * SUN_MAX_DEVICES)) == NULL )
++ {
++ result = paInsufficientMemory;
++ goto error;
++ }
++
++ for( i=0; i < SUN_MAX_DEVICES; ++i )
++ {
++ PaDeviceInfo *dev;
++ struct audio_info hwfmt, info;
++ char path[16];
++ int props;
++
++ if( i > 0 )
++ (void)snprintf(path, sizeof(path), SUN_DEV_PREFIX "%d", i - 1);
++ else
++ (void)snprintf(path, sizeof(path), SUN_DEV_DEFAULT);
++
++ if( (fd = open(path, O_WRONLY | O_NONBLOCK)) < 0 ||
++ (fd = open(path, O_RDONLY | O_NONBLOCK)) < 0 )
++ continue;
++
++ PA_UNLESS(dev = PaUtil_GroupAllocateMemory(sunHostApi->allocations, sizeof(PaDeviceInfo)), paInsufficientMemory);
++
++ dev->structVersion = 2;
++ dev->hostApi = hostApiIndex;
++
++ PA_UNLESS(dev->name = PaUtil_GroupAllocateMemory(sunHostApi->allocations, sizeof(path)), paInsufficientMemory);
++
++ memcpy((char *)dev->name, path, sizeof(path));
++
++ dev->defaultSampleRate = 48000.;
++
++ dev->maxInputChannels = dev->maxOutputChannels = SUN_DEFAULT_MAX_CHANNELS;
++
++ dev->defaultLowInputLatency =
++ dev->defaultLowOutputLatency =
++ dev->defaultHighInputLatency =
++ dev->defaultHighOutputLatency = .04;
++
++#ifdef AUDIO_GETPROPS
++ if( ioctl(fd, AUDIO_GETPROPS, &props) != -1 )
++ {
++ if( (props & AUDIO_PROP_PLAYBACK) == 0 )
++ dev->maxOutputChannels = 0;
++ if( (props & AUDIO_PROP_CAPTURE) == 0 )
++ dev->maxInputChannels = 0;
++ }
++#endif
++
++#ifdef AUDIO_GETFORMAT
++ if( ioctl(fd, AUDIO_GETFORMAT, &hwfmt) != -1 )
++ {
++ if( dev->maxInputChannels > hwfmt.record.channels )
++ dev->maxInputChannels = hwfmt.record.channels;
++ if( dev->maxOutputChannels > hwfmt.play.channels )
++ dev->maxOutputChannels = hwfmt.play.channels;
++ dev->defaultSampleRate = (dev->maxOutputChannels > 0) ?
++ hwfmt.play.sample_rate : hwfmt.record.sample_rate;
++ }
++#endif
++
++#ifdef AUDIO_GETBUFINFO
++ AUDIO_INITINFO(&info);
++ if( dev->maxOutputChannels > 0 )
++ {
++ info.play.encoding = AUDIO_ENCODING_SLINEAR;
++ info.play.precision = 16;
++ info.play.sample_rate = dev->defaultSampleRate;
++ info.play.channels = dev->maxOutputChannels;
++ }
++ if( dev->maxInputChannels > 0 )
++ {
++ info.record.encoding = AUDIO_ENCODING_SLINEAR;
++ info.record.precision = 16;
++ info.record.sample_rate = dev->defaultSampleRate;
++ info.record.channels = dev->maxInputChannels;
++ }
++ if( ioctl(fd, AUDIO_SETINFO, &info) != -1 &&
++ ioctl(fd, AUDIO_GETBUFINFO, &info) != -1 )
++ {
++ if( dev->maxOutputChannels > 0 )
++ {
++ dev->defaultLowOutputLatency =
++ dev->defaultHighOutputLatency =
++ info.blocksize / (info.play.channels * (info.play.precision / 8)) /
++ (double)info.play.sample_rate;
++ }
++ if( dev->maxInputChannels > 0 )
++ {
++ dev->defaultLowInputLatency =
++ dev->defaultHighInputLatency =
++ info.blocksize / (info.record.channels * (info.record.precision / 8)) /
++ (double)info.record.sample_rate;
++ }
++ }
++#endif
++
++ if( common->info.defaultInputDevice == paNoDevice && dev->maxInputChannels > 0 )
++ common->info.defaultInputDevice = deviceCount;
++
++ if( common->info.defaultOutputDevice == paNoDevice && dev->maxOutputChannels > 0 )
++ common->info.defaultOutputDevice = deviceCount;
++
++ common->deviceInfos[deviceCount++] = dev;
++
++ close(fd);
++ fd = -1;
++ }
++
++ common->info.deviceCount = deviceCount;
++
++ *hostApi = common;
++
++ PaUtil_InitializeStreamInterface( &sunHostApi->callbackStreamInterface, CloseStream, StartStream,
++ StopStream, AbortStream, IsStreamStopped, IsStreamActive,
++ GetStreamTime, GetStreamCpuLoad,
++ PaUtil_DummyRead, PaUtil_DummyWrite,
++ PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
++
++ PaUtil_InitializeStreamInterface( &sunHostApi->blockingStreamInterface, CloseStream, StartStream,
++ StopStream, AbortStream, IsStreamStopped, IsStreamActive,
++ GetStreamTime, PaUtil_DummyGetCpuLoad,
++ ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
++ return result;
++
++error:
++ if( fd != -1 )
++ close(fd);
++
++ if( sunHostApi )
++ {
++ if( sunHostApi->allocations )
++ {
++ PaUtil_FreeAllAllocations( sunHostApi->allocations );
++ PaUtil_DestroyAllocationGroup( sunHostApi->allocations );
++ }
++ free( sunHostApi );
++ }
++ return result;
++}
++
++
++static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
++{
++ PaSunHostApiRepresentation *sunHostApi = (PaSunHostApiRepresentation*)hostApi;
++
++ if( sunHostApi )
++ {
++ if( sunHostApi->allocations )
++ {
++ PaUtil_FreeAllAllocations( sunHostApi->allocations );
++ PaUtil_DestroyAllocationGroup( sunHostApi->allocations );
++ }
++ free( sunHostApi );
++ }
++}
++
++
++static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
++ const PaStreamParameters *inputParameters,
++ const PaStreamParameters *outputParameters,
++ double sampleRate )
++{
++ int inputChannelCount, outputChannelCount;
++ PaSampleFormat inputSampleFormat, outputSampleFormat;
++ PaError result = paFormatIsSupported;
++ PaDeviceInfo *indev, *outdev;
++ struct audio_info info;
++ int fd = -1;
++
++ if( inputParameters )
++ {
++ inputChannelCount = inputParameters->channelCount;
++ inputSampleFormat = inputParameters->sampleFormat;
++
++ /* all standard sample formats are supported by the buffer adapter,
++ this implementation doesn't support any custom sample formats */
++ if( inputSampleFormat & paCustomFormat )
++ return paSampleFormatNotSupported;
++
++ /* unless alternate device specification is supported, reject the use of
++ paUseHostApiSpecificDeviceSpecification */
++
++ if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
++ return paInvalidDevice;
++
++ indev = hostApi->deviceInfos[ inputParameters->device ];
++
++ /* check that input device can support inputChannelCount */
++ if( inputChannelCount > indev->maxInputChannels )
++ return paInvalidChannelCount;
++
++ /* validate inputStreamInfo */
++ if( inputParameters->hostApiSpecificStreamInfo )
++ return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
++ }
++ else
++ {
++ inputChannelCount = 0;
++ }
++
++ if( outputParameters )
++ {
++ outputChannelCount = outputParameters->channelCount;
++ outputSampleFormat = outputParameters->sampleFormat;
++
++ /* all standard sample formats are supported by the buffer adapter,
++ this implementation doesn't support any custom sample formats */
++ if( outputSampleFormat & paCustomFormat )
++ return paSampleFormatNotSupported;
++
++ /* unless alternate device specification is supported, reject the use of
++ paUseHostApiSpecificDeviceSpecification */
++
++ if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
++ return paInvalidDevice;
++
++ outdev = hostApi->deviceInfos[ outputParameters->device ];
++
++ /* check that output device can support outputChannelCount */
++ if( outputChannelCount > outdev->maxOutputChannels )
++ return paInvalidChannelCount;
++
++ /* validate outputStreamInfo */
++ if( outputParameters->hostApiSpecificStreamInfo )
++ return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
++ }
++ else
++ {
++ outputChannelCount = 0;
++ }
++
++ if( inputChannelCount > 0 && outputChannelCount > 0 )
++ {
++ if( strcmp(indev->name, outdev->name) == 0 )
++ {
++ PA_UNLESS( (fd = open(indev->name, O_RDWR | O_NONBLOCK)) != -1, paDeviceUnavailable );
++ AUDIO_INITINFO(&info);
++ info.play.channels = outputChannelCount;
++ info.record.channels = inputChannelCount;
++ PA_UNLESS( ioctl(fd, AUDIO_SETINFO, &info) != -1, paInvalidChannelCount );
++ AUDIO_INITINFO(&info);
++ info.play.sample_rate = sampleRate;
++ info.record.sample_rate = sampleRate;
++ PA_UNLESS( ioctl(fd, AUDIO_SETINFO, &info) != -1, paInvalidSampleRate );
++ close(fd);
++ return result;
++ }
++ }
++
++ if( inputChannelCount > 0 )
++ {
++ PA_UNLESS( (fd = open(indev->name, O_RDONLY | O_NONBLOCK)) != -1, paDeviceUnavailable );
++ AUDIO_INITINFO(&info);
++ info.record.channels = inputChannelCount;
++ PA_UNLESS( ioctl(fd, AUDIO_SETINFO, &info) != -1, paInvalidChannelCount );
++ AUDIO_INITINFO(&info);
++ info.record.sample_rate = sampleRate;
++ PA_UNLESS( ioctl(fd, AUDIO_SETINFO, &info) != -1, paInvalidSampleRate );
++ close(fd);
++ fd = -1;
++ }
++
++ if( outputChannelCount > 0 )
++ {
++ PA_UNLESS( (fd = open(outdev->name, O_WRONLY | O_NONBLOCK)) != -1, paDeviceUnavailable );
++ AUDIO_INITINFO(&info);
++ info.play.channels = outputChannelCount;
++ PA_UNLESS( ioctl(fd, AUDIO_SETINFO, &info) != -1, paInvalidChannelCount );
++ AUDIO_INITINFO(&info);
++ info.play.sample_rate = sampleRate;
++ PA_UNLESS( ioctl(fd, AUDIO_SETINFO, &info) != -1, paInvalidSampleRate );
++ close(fd);
++ fd = -1;
++ }
++
++error:
++ if( result == paInvalidChannelCount )
++ PA_DEBUG(("PaSun %s: Invalid channels %d in %d out\n", __FUNCTION__, inputChannelCount, outputChannelCount));
++ if( result == paInvalidSampleRate )
++ PA_DEBUG(("PaSun %s: Invalid sample rate %d Hz\n", __FUNCTION__, (int)sampleRate));
++ if( fd != -1 )
++ close(fd);
++ return result;
++}
++
++typedef struct PaSunComponent
++{
++ int fd;
++ char name[16];
++ void *chanbufs[16];
++ void *buffer;
++ unsigned int bufferSize; /* in frames */
++ unsigned int channels;
++ unsigned int frameSize; /* precision in bytes * channel count */
++}
++PaSunComponent;
++
++typedef struct PaSunStream
++{
++ PaUtilStreamRepresentation streamRepresentation;
++ PaUtilCpuLoadMeasurer cpuLoadMeasurer;
++ PaUtilBufferProcessor bufferProcessor;
++ PaUtilThreading threading;
++ PaSunComponent play, record;
++ bool active, stopped;
++ bool neverDropInput;
++ uint64_t framesProcessed;
++ uint64_t eof;
++ double sampleRate;
++}
++PaSunStream;
++
++/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */
++
++static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
++ PaStream** s,
++ const PaStreamParameters *inputParameters,
++ const PaStreamParameters *outputParameters,
++ double sampleRate,
++ unsigned long framesPerBuffer,
++ PaStreamFlags streamFlags,
++ PaStreamCallback *streamCallback,
++ void *userData )
++{
++ PaError result = paNoError;
++ PaSunHostApiRepresentation *sunHostApi = (PaSunHostApiRepresentation*)hostApi;
++ PaSunStream *stream = 0;
++ unsigned long framesPerHostBuffer = framesPerBuffer; /* these may not be equivalent for all implementations */
++ int inputChannelCount, outputChannelCount;
++ PaSampleFormat inputSampleFormat, outputSampleFormat;
++ PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;
++ PaTime inputLatency = .04, outputLatency = .04;
++ PaDeviceInfo *indev, *outdev;
++ struct audio_info info;
++
++ /* validate platform specific flags */
++ if( (streamFlags & paPlatformSpecificFlags) != 0 )
++ return paInvalidFlag; /* unexpected platform specific flag */
++
++ if( inputParameters )
++ {
++ inputChannelCount = inputParameters->channelCount;
++ inputSampleFormat = inputParameters->sampleFormat;
++
++ /* unless alternate device specification is supported, reject the use of
++ paUseHostApiSpecificDeviceSpecification */
++
++ if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
++ return paInvalidDevice;
++
++ indev = hostApi->deviceInfos[ inputParameters->device ];
++
++ /* check that input device can support inputChannelCount */
++ if( inputChannelCount > indev->maxInputChannels )
++ return paInvalidChannelCount;
++
++ /* validate inputStreamInfo */
++ if( inputParameters->hostApiSpecificStreamInfo )
++ return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
++ }
++ else
++ {
++ inputChannelCount = 0;
++ inputSampleFormat = hostInputSampleFormat = paInt16; /* Surpress 'uninitialised var' warnings. */
++ }
++
++ if( outputParameters )
++ {
++ outputChannelCount = outputParameters->channelCount;
++ outputSampleFormat = outputParameters->sampleFormat;
++
++ /* unless alternate device specification is supported, reject the use of
++ paUseHostApiSpecificDeviceSpecification */
++
++ if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
++ return paInvalidDevice;
++
++ outdev = hostApi->deviceInfos[ outputParameters->device ];
++
++ /* check that output device can support outputChannelCount */
++ if( outputChannelCount > outdev->maxOutputChannels )
++ return paInvalidChannelCount;
++
++ /* validate outputStreamInfo */
++ if( outputParameters->hostApiSpecificStreamInfo )
++ return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
++ }
++ else
++ {
++ outputChannelCount = 0;
++ outputSampleFormat = hostOutputSampleFormat = paInt16; /* Surpress 'uninitialized var' warnings. */
++ }
++
++ PA_UNLESS(stream = calloc( 1, sizeof(PaSunStream) ), paInsufficientMemory);
++
++ stream->play.fd = stream->record.fd = -1;
++ stream->stopped = true;
++ stream->neverDropInput = streamFlags & paNeverDropInput;
++
++ if( inputChannelCount > 0 && outputChannelCount > 0)
++ {
++ if( inputParameters->device == outputParameters->device )
++ {
++ PA_DEBUG(("PaSun %s: Opening device %s in full duplex\n", __FUNCTION__, indev->name));
++ PA_UNLESS( (stream->play.fd = open(indev->name, O_RDWR)) != -1, paDeviceUnavailable );
++ stream->record.fd = stream->play.fd;
++ }
++ }
++
++ if( inputChannelCount > 0 )
++ {
++ if( stream->record.fd == -1 )
++ PA_UNLESS((stream->record.fd = open(indev->name, O_RDONLY)) != -1, paDeviceUnavailable);
++
++ memcpy(stream->record.name, indev->name, strlen(indev->name));
++
++ hostInputSampleFormat =
++ PaUtil_SelectClosestAvailableFormat( GetSupportedEncodings(stream->record.fd, true), inputSampleFormat );
++
++ AUDIO_INITINFO(&info);
++ if( PaFormatToSunFormat(hostInputSampleFormat, &info.record ) != paNoError ||
++ ioctl(stream->record.fd, AUDIO_SETINFO, &info) < 0 )
++ {
++ result = paSampleFormatNotSupported;
++ goto error;
++ }
++
++ AUDIO_INITINFO(&info);
++ info.record.sample_rate = sampleRate;
++ PA_UNLESS( ioctl(stream->record.fd, AUDIO_SETINFO, &info) != -1, paInvalidSampleRate );
++
++ AUDIO_INITINFO(&info);
++ info.record.channels = inputChannelCount;
++ PA_UNLESS( ioctl(stream->record.fd, AUDIO_SETINFO, &info) != -1, paInvalidChannelCount );
++
++ PA_UNLESS( ioctl(stream->record.fd, AUDIO_GETINFO, &info) != -1, paDeviceUnavailable );
++
++ PA_DEBUG(("PaSun %s: %u-bit %u-channel recording stream at %u Hz\n", __FUNCTION__,
++ info.record.precision, info.record.channels, info.record.sample_rate));
++
++ sampleRate = info.record.sample_rate;
++
++ stream->record.channels = inputChannelCount = info.record.channels;
++ stream->record.frameSize = (info.record.precision / 8) * info.record.channels;
++ stream->record.bufferSize = framesPerBuffer;
++
++#ifdef AUDIO_GETBUFINFO
++ inputLatency = (info.blocksize / stream->record.frameSize) +
++ PaUtil_GetBufferProcessorInputLatencyFrames( &stream->bufferProcessor ) / sampleRate;
++#else
++ inputLatency += PaUtil_GetBufferProcessorInputLatencyFrames( &stream->bufferProcessor ) / sampleRate;
++#endif
++
++ if( framesPerBuffer == paFramesPerBufferUnspecified )
++ {
++#ifdef AUDIO_GETBUFINFO
++ stream->record.bufferSize = info.blocksize / stream->record.frameSize;
++#else
++ stream->record.bufferSize = SUN_DEFAULT_FRAMES;
++#endif
++ framesPerBuffer = framesPerHostBuffer = stream->record.bufferSize;
++ }
++
++ PA_UNLESS(stream->record.buffer = calloc(stream->record.bufferSize, stream->record.frameSize), paInsufficientMemory);
++ }
++
++ if( outputChannelCount > 0 )
++ {
++ if( stream->play.fd == -1 )
++ PA_UNLESS((stream->play.fd = open(outdev->name, O_WRONLY)) != -1, paDeviceUnavailable);
++
++ memcpy(stream->play.name, outdev->name, strlen(outdev->name));
++
++ hostOutputSampleFormat =
++ PaUtil_SelectClosestAvailableFormat( GetSupportedEncodings(stream->play.fd, false), outputSampleFormat );
++
++ AUDIO_INITINFO(&info);
++ if( PaFormatToSunFormat(hostOutputSampleFormat, &info.play ) != paNoError ||
++ ioctl(stream->play.fd, AUDIO_SETINFO, &info) < 0 )
++ {
++ result = paSampleFormatNotSupported;
++ goto error;
++ }
++
++ AUDIO_INITINFO(&info);
++ info.play.sample_rate = sampleRate;
++ PA_UNLESS( ioctl(stream->play.fd, AUDIO_SETINFO, &info) != -1, paInvalidSampleRate );
++
++ AUDIO_INITINFO(&info);
++ info.play.channels = outputChannelCount;
++ PA_UNLESS( ioctl(stream->play.fd, AUDIO_SETINFO, &info) != -1, paInvalidChannelCount );
++
++ PA_UNLESS( ioctl(stream->play.fd, AUDIO_GETINFO, &info) != -1, paDeviceUnavailable );
++
++ PA_DEBUG(("PaSun %s: %u-bit %u-channel playback stream at %u Hz\n", __FUNCTION__,
++ info.play.precision, info.play.channels, info.play.sample_rate));
++
++ sampleRate = info.play.sample_rate;
++
++ stream->play.channels = outputChannelCount = info.play.channels;
++ stream->play.frameSize = (info.play.precision / 8) * info.play.channels;
++ stream->play.bufferSize = framesPerBuffer;
++
++#ifdef AUDIO_GETBUFINFO
++ outputLatency = (info.blocksize / stream->play.frameSize) +
++ PaUtil_GetBufferProcessorOutputLatencyFrames( &stream->bufferProcessor ) / sampleRate;
++#else
++ outputLatency += PaUtil_GetBufferProcessorInputLatencyFrames( &stream->bufferProcessor ) / sampleRate;
++#endif
++
++ if( framesPerBuffer == paFramesPerBufferUnspecified )
++ {
++#ifdef AUDIO_GETBUFINFO
++ stream->play.bufferSize = info.blocksize / stream->play.frameSize;
++#else
++ stream->play.bufferSize = SUN_DEFAULT_FRAMES;
++#endif
++ framesPerBuffer = framesPerHostBuffer = stream->play.bufferSize;
++ }
++
++ PA_UNLESS( stream->play.buffer = calloc(stream->play.bufferSize, stream->play.frameSize), paInsufficientMemory );
++ }
++
++ stream->sampleRate = sampleRate;
++
++ if( streamCallback )
++ {
++ PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
++ &sunHostApi->callbackStreamInterface, streamCallback, userData );
++ }
++ else
++ {
++ PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
++ &sunHostApi->blockingStreamInterface, streamCallback, userData );
++ }
++
++ PA_ENSURE( PaUtil_InitializeThreading( &stream->threading ) );
++
++ PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
++
++ /* we assume a fixed host buffer size in this example, but the buffer processor
++ can also support bounded and unknown host buffer sizes by passing
++ paUtilBoundedHostBufferSize or paUtilUnknownHostBufferSize instead of
++ paUtilFixedHostBufferSize below. */
++
++ result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
++ inputChannelCount, inputSampleFormat, hostInputSampleFormat,
++ outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
++ sampleRate, streamFlags, framesPerBuffer,
++ framesPerHostBuffer, paUtilFixedHostBufferSize,
++ streamCallback, userData );
++ if( result != paNoError )
++ goto error;
++
++ stream->streamRepresentation.streamInfo.inputLatency = inputLatency;
++ stream->streamRepresentation.streamInfo.outputLatency = outputLatency;
++ stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
++
++ *s = (PaStream*)stream;
++
++ return result;
++
++error:
++ if( stream != NULL )
++ {
++ if( stream->play.fd != -1)
++ close( stream->play.fd );
++ if( stream->record.fd != -1 && stream->record.fd != stream->play.fd )
++ close( stream->record.fd );
++ free( stream->play.buffer );
++ free( stream->record.buffer );
++ free( stream );
++ }
++ return result;
++}
++
++static void *PaSun_AudioThreadProc( void *userData )
++{
++ PaError result = paNoError;
++ PaSunStream *stream = (PaSunStream*)userData;
++ PaStreamCallbackTimeInfo timeInfo = {0,0,0};
++ int callbackResult;
++ struct audio_info info;
++ unsigned int pframes, rframes;
++ size_t off;
++
++ while(!stream->stopped)
++ {
++ pframes = rframes = 0;
++
++ if( stream->play.channels > 0 )
++ pframes = stream->play.bufferSize;
++
++ if( stream->record.channels > 0 )
++ rframes = stream->record.bufferSize;
++
++ if( rframes > 0 )
++ {
++ ssize_t len = rframes * stream->record.frameSize;
++ PA_ENSURE( (len = read(stream->record.fd, stream->record.buffer, len)) != -1 );
++ rframes = len / stream->record.frameSize;
++ if( pframes > rframes )
++ pframes = rframes;
++ }
++
++ PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
++ PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, 0 );
++
++ if( rframes > 0 )
++ {
++ PaUtil_SetInputFrameCount( &stream->bufferProcessor, rframes );
++ PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor, 0, stream->record.buffer, stream->record.channels );
++ }
++ else if ( stream->record.channels > 0 )
++ {
++ PaUtil_SetNoInput( &stream->bufferProcessor );
++ }
++
++ if( pframes > 0 )
++ {
++ PaUtil_SetOutputFrameCount( &stream->bufferProcessor, pframes );
++ PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, 0, stream->play.buffer, stream->play.channels );
++ }
++ else if ( stream->play.channels > 0 && stream->neverDropInput )
++ {
++ PaUtil_SetNoOutput( &stream->bufferProcessor );
++ }
++
++ callbackResult = paContinue;
++ pframes = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &callbackResult );
++ PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, pframes );
++
++ stream->framesProcessed += pframes;
++
++ off = 0;
++
++ while( stream->play.channels > 0 && pframes > 0 )
++ {
++ ssize_t len = pframes * stream->play.frameSize;
++ PA_ENSURE( (len = write(stream->play.fd, stream->play.buffer + off, len)) != -1 );
++ pframes -= (len / stream->play.frameSize);
++ off += len;
++ }
++
++ if( callbackResult != paContinue )
++ break;
++ }
++
++ if( callbackResult == paAbort )
++ {
++ /* once finished, call the finished callback */
++ if( stream->streamRepresentation.streamFinishedCallback != 0 )
++ stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
++ }
++ else
++ {
++ /* once finished, call the finished callback */
++ if( stream->streamRepresentation.streamFinishedCallback != 0 )
++ stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
++ }
++
++error:
++ PaUtil_ResetCpuLoadMeasurer( &stream->cpuLoadMeasurer );
++ stream->active = false;
++ PA_DEBUG(("PaSun %s: Thread exited\n", __FUNCTION__));
++ pthread_exit( NULL );
++}
++
++/*
++ When CloseStream() is called, the multi-api layer ensures that
++ the stream has already been stopped or aborted.
++*/
++static PaError CloseStream( PaStream* s )
++{
++ PaError result = paNoError;
++ PaSunStream *stream = (PaSunStream*)s;
++
++ PaUtil_TerminateThreading ( &stream->threading );
++ PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
++ PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
++
++ if( stream->play.fd != -1 )
++ close(stream->play.fd);
++
++ if( stream->record.fd != -1 && stream->record.fd != stream->play.fd )
++ close(stream->record.fd);
++
++ free( stream->play.buffer );
++ free( stream->record.buffer );
++ free( stream );
++
++ return result;
++}
++
++
++static PaError StartStream( PaStream *s )
++{
++ PaError result = paNoError;
++ PaSunStream *stream = (PaSunStream*)s;
++
++ PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
++
++ stream->active = true;
++ stream->stopped = false;
++
++ if( stream->bufferProcessor.streamCallback )
++ PA_ENSURE( PaUtil_StartThreading( &stream->threading, &PaSun_AudioThreadProc, stream ) );
++
++error:
++ return result;
++}
++
++
++static PaError StopStream( PaStream *s )
++{
++ PaError result = paNoError;
++ PaSunStream *stream = (PaSunStream*)s;
++
++ stream->stopped = true;
++
++ if( stream->bufferProcessor.streamCallback )
++ PA_ENSURE( PaUtil_CancelThreading( &stream->threading, 1, NULL ) );
++
++ if( stream->play.fd != -1 )
++ (void)ioctl(stream->play.fd, AUDIO_DRAIN);
++
++error:
++ return result;
++}
++
++static PaError AbortStream( PaStream *s )
++{
++ PaError result = paNoError;
++ PaSunStream *stream = (PaSunStream*)s;
++
++ stream->stopped = true;
++
++ if( stream->bufferProcessor.streamCallback )
++ PA_ENSURE( PaUtil_CancelThreading( &stream->threading, 0, NULL ) );
++
++ if( stream->play.fd != -1 )
++ (void)ioctl(stream->play.fd, AUDIO_FLUSH);
++
++error:
++ return result;
++}
++
++static PaError IsStreamStopped( PaStream *s )
++{
++ PaSunStream *stream = (PaSunStream*)s;
++
++ return stream->stopped;
++}
++
++
++static PaError IsStreamActive( PaStream *s )
++{
++ PaSunStream *stream = (PaSunStream*)s;
++
++ return stream->active;
++}
++
++
++static PaTime GetStreamTime( PaStream *s )
++{
++ PaSunStream *stream = (PaSunStream*)s;
++
++ return stream->framesProcessed / stream->sampleRate;
++}
++
++
++static double GetStreamCpuLoad( PaStream* s )
++{
++ PaSunStream *stream = (PaSunStream*)s;
++
++ return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
++}
++
++
++/*
++ As separate stream interfaces are used for blocking and callback
++ streams, the following functions can be guaranteed to only be called
++ for blocking streams.
++*/
++
++static PaError ReadStream( PaStream* s,
++ void *buffer,
++ unsigned long frames )
++{
++ PaSunStream *stream = (PaSunStream*)s;
++ void *chanbufs = buffer;
++ unsigned wantframes, wantbytes;
++
++ /* If user output is non-interleaved, PaUtil_CopyInput will manipulate the channel pointers,
++ * so we copy the user provided pointers */
++ if( !stream->bufferProcessor.userInputIsInterleaved )
++ {
++ /* Copy channels into local array */
++ chanbufs = stream->play.chanbufs;
++ memcpy( chanbufs, buffer, sizeof (void *) * stream->record.channels );
++ }
++
++ while( frames )
++ {
++ wantframes = PA_MIN( frames, stream->record.bufferSize );
++ wantbytes = wantframes * stream->record.frameSize;
++
++ if ( read(stream->record.fd, stream->record.buffer, wantbytes) < wantbytes )
++ return paUnanticipatedHostError;
++
++ PaUtil_SetInputFrameCount( &stream->bufferProcessor, stream->record.bufferSize );
++ PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor, 0, stream->record.buffer, stream->record.channels );
++ PaUtil_CopyInput( &stream->bufferProcessor, &chanbufs, wantframes );
++
++ frames -= wantframes;
++ }
++
++ return paNoError;
++}
++
++
++static PaError WriteStream( PaStream* s,
++ const void *buffer,
++ unsigned long frames )
++{
++ PaSunStream *stream = (PaSunStream*)s;
++ const void *chanbufs = buffer;
++ unsigned nbytes;
++ unsigned long gotframes;
++
++ /* If user output is non-interleaved, PaUtil_CopyOutput will manipulate the channel pointers,
++ * so we copy the user provided pointers */
++ if( !stream->bufferProcessor.userOutputIsInterleaved )
++ {
++ /* Copy channels into local array */
++ chanbufs = stream->play.chanbufs;
++ memcpy( (void *)chanbufs, buffer, sizeof (void *) * stream->play.channels );
++ }
++
++ while( frames )
++ {
++ PaUtil_SetOutputFrameCount( &stream->bufferProcessor, stream->play.bufferSize );
++ PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, 0, stream->play.buffer, stream->play.channels );
++
++ gotframes = PaUtil_CopyOutput( &stream->bufferProcessor, &chanbufs, frames );
++
++ nbytes = gotframes * stream->play.frameSize;
++
++ if( write(stream->play.fd, stream->play.buffer, nbytes) < nbytes )
++ return paUnanticipatedHostError;
++
++ frames -= gotframes;
++ }
++ if( write(stream->play.fd, stream->play.buffer, 0) < 0 )
++ return paUnanticipatedHostError;
++ stream->eof++;
++ return paNoError;
++}
++
++
++static signed long GetStreamReadAvailable( PaStream* s )
++{
++ PaSunStream *stream = (PaSunStream*)s;
++#ifdef AUDIO_GETBUFINFO
++ struct audio_info info;
++
++ if( ioctl(stream->record.fd, AUDIO_GETBUFINFO, &info) == -1 )
++ return paDeviceUnavailable;
++
++ return info.record.seek / stream->record.frameSize;
++#else
++ struct pollfd pfd[1];
++
++ memset(pfd, 0, sizeof(pfd));
++ pfd[0].fd = stream->record.fd;
++ pfd[0].events = POLLIN;
++
++ if( poll(pfd, 1, 0) == -1 )
++ return paDeviceUnavailable;
++
++ return (pfd[0].revents & POLLIN) ? SUN_DEFAULT_FRAMES : 0;
++#endif
++}
++
++
++static signed long GetStreamWriteAvailable( PaStream* s )
++{
++ PaSunStream *stream = (PaSunStream*)s;
++ struct audio_info info;
++
++#ifdef AUDIO_GETBUFINFO
++ if( ioctl(stream->play.fd, AUDIO_GETBUFINFO, &info) == -1 )
++ return paDeviceUnavailable;
++
++ return ((info.hiwat * info.blocksize) - info.play.seek) / stream->play.frameSize;
++#else
++ if( ioctl(stream->play.fd, AUDIO_GETINFO, &info) == -1 )
++ return paDeviceUnavailable;
++
++ if( (stream->eof - info.play.eof) > 2 )
++ return 0;
++
++ return SUN_DEFAULT_FRAMES;
++#endif
++}
++
++static PaError PaFormatToSunFormat( PaSampleFormat fmt, struct audio_prinfo *info )
++{
++ PaError err = paNoError;
++
++ switch( fmt )
++ {
++ case paInt32:
++ info->encoding = AUDIO_ENCODING_SLINEAR;
++ info->precision = 32;
++ break;
++ case paInt16:
++ info->encoding = AUDIO_ENCODING_SLINEAR;
++ info->precision = 16;
++ break;
++ case paInt8:
++ info->encoding = AUDIO_ENCODING_SLINEAR;
++ info->precision = 8;
++ break;
++ default:
++ err = paSampleFormatNotSupported;
++ break;
++ }
++ return err;
++}
++
++static bool AttemptEncoding( int fd, int encoding, int precision, bool record )
++{
++ struct audio_info info;
++ struct audio_prinfo *prinfo = record ? &info.record : &info.play;
++
++ AUDIO_INITINFO(&info);
++ prinfo->encoding = encoding;
++ prinfo->precision = precision;
++
++ return ioctl(fd, AUDIO_SETINFO, &info) != -1;
++}
++
++static PaSampleFormat GetSupportedEncodings( int fd, bool record )
++{
++ PaSampleFormat fmts = 0;
++
++ if( AttemptEncoding(fd, AUDIO_ENCODING_SLINEAR, 32, record) )
++ fmts |= paInt32;
++
++ if( AttemptEncoding(fd, AUDIO_ENCODING_SLINEAR, 16, record) )
++ fmts |= paInt16;
++
++ if( AttemptEncoding(fd, AUDIO_ENCODING_SLINEAR, 8, record) )
++ fmts |= paInt8;
++
++ return fmts;
++}
Index: pkgsrc/audio/portaudio/patches/patch-src_os_unix_pa__unix__hostapis.c
diff -u /dev/null pkgsrc/audio/portaudio/patches/patch-src_os_unix_pa__unix__hostapis.c:1.1
--- /dev/null Fri Apr 17 15:50:03 2020
+++ pkgsrc/audio/portaudio/patches/patch-src_os_unix_pa__unix__hostapis.c Fri Apr 17 15:50:03 2020
@@ -0,0 +1,25 @@
+$NetBSD: patch-src_os_unix_pa__unix__hostapis.c,v 1.1 2020/04/17 15:50:03 nia Exp $
+
+Sun/NetBSD audio support.
+
+--- src/os/unix/pa_unix_hostapis.c.orig 2016-10-30 01:23:04.000000000 +0000
++++ src/os/unix/pa_unix_hostapis.c
+@@ -45,6 +45,7 @@
+ PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+ PaError PaAlsa_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+ PaError PaOSS_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
++PaError PaSun_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+ /* Added for IRIX, Pieter, oct 2, 2003: */
+ PaError PaSGI_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+ /* Linux AudioScience HPI */
+@@ -69,6 +70,10 @@ PaUtilHostApiInitializer *paHostApiIniti
+
+ #else /* __linux__ */
+
++#if PA_USE_SUN
++ PaSun_Initialize,
++#endif
++
+ #if PA_USE_OSS
+ PaOSS_Initialize,
+ #endif
Home |
Main Index |
Thread Index |
Old Index