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