On Tue, Jan 14, 2020 at 03:10:11PM +0000, Stuart Henderson wrote:
> On 2020/01/13 21:34, Mark Hesselink wrote:
> > Dear list,
> >
> > Please find attached a sndio(7) sound driver for Squeak VM 3.10.1
> > (lang/squeak/vm). This driver has been fairly extensively tested by my
> > family over the course of several weeks trying to implement the examples
> > listed in Coding for Beginners Using Scratch by Jonathan Melmoth et al using
> > Scratch 1.4.
> >
> > The tarball contains the following files:
> <snip>
>
> Oh, nice! Here's a diff against the ports tree to add it all in. I had to
> convert some existing patches which had been done against autoconf "output
> files" to touch the input files instead.
>
> > * GNUmakefile, bump-epoch.awk: GNU make based makefile plus helper files
> > which I used while developing the driver.
>
> btw, EPOCH is used for "version going backwards" (and can never be removed
> once it's added to a port), for a normal update just REVISION is used.
> I mention this because you will probably have some files in /usr/ports/plist
> relating to your previous tests that you may need to remove before you can
> build a package directly from ports.
>
> Diff inline below, or at https://junkpile.org/squeak-sndio.diff in case
> there are any problems with it getting mangled through mail (should be OK
> though).
>
> I don't have a machine with working audio handy right now, if you (or
> someone else) could confirm that it's working as expected with this diff
> then as long as the maintainer (CC'd) is happy with it then I can commit.
>
> Index: Makefile
> ===================================================================
> RCS file: /cvs/ports/lang/squeak/vm/Makefile,v
> retrieving revision 1.28
> diff -u -p -r1.28 Makefile
> --- Makefile 25 Dec 2017 07:04:45 -0000 1.28
> +++ Makefile 14 Jan 2020 14:59:57 -0000
> @@ -6,19 +6,27 @@ SRCV = 1
> DISTFILES = Squeak-$V-${SRCV}.src.tar.gz
>
> PKGNAME = squeak-vm-$V.${SRCV}
> -REVISION = 9
> +REVISION = 10
>
> WRKDIST = ${WRKDIR}/Squeak-$V-${SRCV}
> WRKSRC = ${WRKDIST}/platforms/unix/config
>
> +WANTLIB += GL ICE SM X11 X11-xcb Xdamage Xext Xfixes Xrender Xt
> +WANTLIB += Xxf86vm c drm expat glapi m pthread sndio util xcb
> +WANTLIB += xcb-dri2 xcb-dri3 xcb-glx xcb-present xcb-sync xcb-xfixes
> +WANTLIB += xshmfence z
> +
> SEPARATE_BUILD = Yes
>
> MASTER_SITES = ${SQUEAK_SITE}unix-linux/
>
> RUN_DEPENDS = squeak-sources-${SOURCEV}:lang/squeak/sources
>
> -CONFIGURE_STYLE = gnu
> -AUTOCONF_VERSION = 2.60
> +CONFIGURE_STYLE = autoreconf
> +AUTOCONF_VERSION = 2.69
> +AUTOMAKE_VERSION = 1.16
> +AUTORECONF = ${MAKE} configure
> +
> DESTDIRNAME = ROOT
> CONFIGURE_ENV = LDFLAGS="-lpthread ${LDFLAGS}" RANLIB=ranlib \
> ac_cv_socklen_t=yes
> @@ -26,8 +34,6 @@ USE_GMAKE = Yes
> USE_LIBTOOL = No
> NO_TEST = Yes
>
> -WANTLIB = GL X11 m c SM util Xext ICE Xrender Xt pthread \
> - xcb
> FULLV = $V-${SRCV}
>
> # XXX gnu-interp doesn't work with pie.
> @@ -41,6 +47,9 @@ MAKE_FLAGS += docdir=${PREFIX}/share/do
> DESTDIRNAME = ROOT
> SUBST_VARS += FULLV
> CFLAGS += -fgnu89-inline
> +
> +pre-patch:
> + @perl -pi -e s,\\r,\\n,g
> ${WRKDIST}/platforms/unix/src/vm/intplugins/SoundPlugin/*.c
>
> pre-build:
> @perl -pi -e s,dprintf,debugprintf, ${WRKDIST}/platforms/unix/vm/*.c
> Index: patches/patch-platforms_unix_config_Makefile
> ===================================================================
> RCS file: patches/patch-platforms_unix_config_Makefile
> diff -N patches/patch-platforms_unix_config_Makefile
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-platforms_unix_config_Makefile 14 Jan 2020 14:59:57
> -0000
> @@ -0,0 +1,11 @@
> +$OpenBSD$
> +
> +Index: platforms/unix/config/Makefile
> +--- platforms/unix/config/Makefile.orig
> ++++ platforms/unix/config/Makefile
> +@@ -1,4 +1,5 @@
> + configure : .force
> ++ libtoolize -c
> + ./mkacinc > acplugins.m4
> + aclocal
> + autoconf
> Index: patches/patch-platforms_unix_config_acinclude_m4
> ===================================================================
> RCS file: patches/patch-platforms_unix_config_acinclude_m4
> diff -N patches/patch-platforms_unix_config_acinclude_m4
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-platforms_unix_config_acinclude_m4 14 Jan 2020 14:59:57
> -0000
> @@ -0,0 +1,24 @@
> +$OpenBSD$
> +
> +fix build on alpha
> +
> +Index: platforms/unix/config/acinclude.m4
> +--- platforms/unix/config/acinclude.m4.orig
> ++++ platforms/unix/config/acinclude.m4
> +@@ -255,16 +255,6 @@ fi)
> + AC_DEFINE_UNQUOTED(VM_MODULE_PREFIX,"$mkfrags_lib_prefix")
> + test "$ac_cv_module_prefix" = lib && mkfrags_lib_prefix=lib])
> +
> +-AC_DEFUN([AC_64BIT_ARCH],
> +-[AC_MSG_CHECKING(for compiler flags to force 32-bit addresses)
> +-case $host in
> +- alpha*)
> +- CFLAGS_32="-taso"
> +- test "$GCC" = "yes" && CC="\$(utldir)/decgcc"
> +- ;;
> +-esac
> +-AC_MSG_RESULT($CFLAGS_32)])
> +-
> +
> + ### plugin support
> +
> Index: patches/patch-platforms_unix_config_configure
> ===================================================================
> RCS file: patches/patch-platforms_unix_config_configure
> diff -N patches/patch-platforms_unix_config_configure
> --- patches/patch-platforms_unix_config_configure 30 Dec 2013 12:14:55
> -0000 1.1
> +++ /dev/null 1 Jan 1970 00:00:00 -0000
> @@ -1,25 +0,0 @@
> -$OpenBSD: patch-platforms_unix_config_configure,v 1.1 2013/12/30 12:14:55
> landry Exp $
> -fix build on alpha
> ---- platforms/unix/config/configure.orig Thu Apr 10 15:48:48 2008
> -+++ platforms/unix/config/configure Mon Dec 30 04:20:56 2013
> -@@ -26202,20 +26202,6 @@ cat >>confdefs.h <<_ACEOF
> - #define VM_MODULE_PREFIX "$mkfrags_lib_prefix"
> - _ACEOF
> -
> --test "$ac_cv_module_prefix" = lib && mkfrags_lib_prefix=lib
> --{ echo "$as_me:$LINENO: checking for compiler flags to force 32-bit
> addresses" >&5
> --echo $ECHO_N "checking for compiler flags to force 32-bit addresses...
> $ECHO_C" >&6; }
> --case $host in
> -- alpha*)
> -- CFLAGS_32="-taso"
> -- test "$GCC" = "yes" && CC="\$(utldir)/decgcc"
> -- ;;
> --esac
> --{ echo "$as_me:$LINENO: result: $CFLAGS_32" >&5
> --echo "${ECHO_T}$CFLAGS_32" >&6; }
> --
> --CFLAGS="$CFLAGS_32 $CFLAGS"
> --
> - { echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
> - echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; }
> - if test "${ac_cv_c_bigendian+set}" = set; then
> Index: patches/patch-platforms_unix_config_configure_ac
> ===================================================================
> RCS file: patches/patch-platforms_unix_config_configure_ac
> diff -N patches/patch-platforms_unix_config_configure_ac
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-platforms_unix_config_configure_ac 14 Jan 2020 14:59:57
> -0000
> @@ -0,0 +1,13 @@
> +$OpenBSD$
> +
> +Index: platforms/unix/config/configure.ac
> +--- platforms/unix/config/configure.ac.orig
> ++++ platforms/unix/config/configure.ac
> +@@ -243,7 +243,6 @@ AC_FUNC_ALLOCA
> + AC_GNU_OPT
> + AC_GNU_INTERP
> + AC_MODULE_LIB_PREFIX
> +-AC_64BIT_ARCH
> +
> + CFLAGS="$CFLAGS_32 $CFLAGS"
> +
> Index: patches/patch-platforms_unix_npsqueak_Makefile
> ===================================================================
> RCS file:
> /cvs/ports/lang/squeak/vm/patches/patch-platforms_unix_npsqueak_Makefile,v
> retrieving revision 1.1
> diff -u -p -r1.1 patch-platforms_unix_npsqueak_Makefile
> --- patches/patch-platforms_unix_npsqueak_Makefile 23 Jul 2008 11:17:22
> -0000 1.1
> +++ patches/patch-platforms_unix_npsqueak_Makefile 14 Jan 2020 14:59:57
> -0000
> @@ -1,6 +1,7 @@
> $OpenBSD: patch-platforms_unix_npsqueak_Makefile,v 1.1 2008/07/23 11:17:22
> espie Exp $
> ---- platforms/unix/npsqueak/Makefile.orig Sat Oct 13 05:03:33 2007
> -+++ platforms/unix/npsqueak/Makefile Wed Jul 23 13:07:25 2008
> +Index: platforms/unix/npsqueak/Makefile
> +--- platforms/unix/npsqueak/Makefile.orig
> ++++ platforms/unix/npsqueak/Makefile
> @@ -8,7 +8,7 @@ INC = -I./include -I/usr/X11R6/include
> CC = gcc
> CFLAGS = $(INC) -O2 -fPIC -Wall
> @@ -10,3 +11,12 @@ $OpenBSD: patch-platforms_unix_npsqueak_
>
> # usually overridden from top level makefile
> VM_VERSION= 3.9-12
> +@@ -26,7 +26,7 @@ all: npsqueak.so npsqueakrun
> +
> + npsqueak.so : npsqueak.la
> + -@rm -f $@
> +- ln .libs/npsqueak $@
> ++ ln .libs/npsqueak.so $@
> +
> + npsqueak.la : npsqueak.lo npunix.lo
> + ../libtool --mode=link $(LD) $(LDFLAGS) npsqueak.lo npunix.lo
> -avoid-version -module -rpath $(plgdir) -o $@
> Index:
> patches/patch-platforms_unix_src_vm_intplugins_SoundPlugin_SoundPlugin_c
> ===================================================================
> RCS file:
> patches/patch-platforms_unix_src_vm_intplugins_SoundPlugin_SoundPlugin_c
> diff -N
> patches/patch-platforms_unix_src_vm_intplugins_SoundPlugin_SoundPlugin_c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-platforms_unix_src_vm_intplugins_SoundPlugin_SoundPlugin_c
> 14 Jan 2020 14:59:57 -0000
> @@ -0,0 +1,87 @@
> +$OpenBSD$
> +
> +Index: platforms/unix/src/vm/intplugins/SoundPlugin/SoundPlugin.c
> +--- platforms/unix/src/vm/intplugins/SoundPlugin/SoundPlugin.c.orig
> ++++ platforms/unix/src/vm/intplugins/SoundPlugin/SoundPlugin.c
> +@@ -211,24 +211,27 @@ EXPORT(sqInt) primitiveSoundInsertSamples(void) {
> + /* Output a buffer's worth of sound samples. */
> +
> + EXPORT(sqInt) primitiveSoundPlaySamples(void) {
> +- sqInt framesPlayed;
> ++ sqInt buffer;
> + sqInt frameCount;
> +- usqInt *buf;
> ++ sqInt framesPlayed;
> + sqInt startIndex;
> + sqInt _return_value;
> ++ char *bufferData;
> +
> + frameCount = interpreterProxy->stackIntegerValue(2);
> +-
> interpreterProxy->success(interpreterProxy->isWords(interpreterProxy->stackValue(1)));
> +- buf = ((unsigned *)
> (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1))));
> ++ buffer = interpreterProxy->stackValue(1);
> + startIndex = interpreterProxy->stackIntegerValue(0);
> ++ interpreterProxy->success(interpreterProxy->isWords(buffer));
> + if (interpreterProxy->failed()) {
> + return null;
> + }
> +- interpreterProxy->success((startIndex >= 1) && (((startIndex +
> frameCount) - 1) <= (interpreterProxy->slotSizeOf(((sqInt)(long)(buf) -
> 4)))));
> +- if (!(interpreterProxy->failed())) {
> +- framesPlayed = snd_PlaySamplesFromAtLength(frameCount,
> (int)buf, startIndex - 1);
> +- interpreterProxy->success(framesPlayed >= 0);
> ++ interpreterProxy->success((startIndex >= 1) && (((startIndex +
> frameCount) - 1) <= (interpreterProxy->slotSizeOf(buffer))));
> ++ if (interpreterProxy->failed()) {
> ++ return null;
> + }
> ++ bufferData = interpreterProxy->firstIndexableField(buffer);
> ++ framesPlayed = snd_PlaySamplesFromAtLength(frameCount,
> oopForPointer(bufferData), startIndex - 1);
> ++ interpreterProxy->success(framesPlayed >= 0);
> + _return_value = interpreterProxy->positive32BitIntegerFor(framesPlayed);
> + if (interpreterProxy->failed()) {
> + return null;
> +@@ -261,25 +264,27 @@ EXPORT(sqInt) primitiveSoundPlaySilence(void) {
> + /* Record a buffer's worth of 16-bit sound samples. */
> +
> + EXPORT(sqInt) primitiveSoundRecordSamples(void) {
> +- sqInt bufSizeInBytes;
> ++ sqInt buffer;
> ++ sqInt bufferSizeInSamples;
> + sqInt samplesRecorded;
> +- usqInt *buf;
> +- sqInt startWordIndex;
> ++ sqInt startIndex;
> + sqInt _return_value;
> ++ char *bufferData;
> +
> +-
> interpreterProxy->success(interpreterProxy->isWords(interpreterProxy->stackValue(1)));
> +- buf = ((unsigned *)
> (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1))));
> +- startWordIndex = interpreterProxy->stackIntegerValue(0);
> ++ buffer = interpreterProxy->stackValue(1);
> ++ startIndex = interpreterProxy->stackIntegerValue(0);
> ++ interpreterProxy->success(interpreterProxy->isWords(buffer));
> + if (interpreterProxy->failed()) {
> + return null;
> + }
> +- if (!(interpreterProxy->failed())) {
> +- bufSizeInBytes =
> (interpreterProxy->slotSizeOf(((sqInt)(long)(buf) - 4))) * 4;
> +- interpreterProxy->success((startWordIndex >= 1) &&
> (((startWordIndex - 1) * 2) < bufSizeInBytes));
> ++ bufferSizeInSamples = interpreterProxy->slotSizeOf(buffer) * 2;
> ++ interpreterProxy->success((startIndex >= 1) && ((startIndex - 1) <=
> bufferSizeInSamples));
> ++ if (interpreterProxy->failed()) {
> ++ return null;
> + }
> +- if (!(interpreterProxy->failed())) {
> +- samplesRecorded = snd_RecordSamplesIntoAtLength((int)buf,
> startWordIndex - 1, bufSizeInBytes);
> +- }
> ++ bufferData = interpreterProxy->firstIndexableField(buffer);
> ++ samplesRecorded =
> snd_RecordSamplesIntoAtLength(oopForPointer(bufferData), startIndex - 1,
> bufferSizeInSamples * 2);
> ++ interpreterProxy->success(samplesRecorded >= 0);
> + _return_value =
> interpreterProxy->positive32BitIntegerFor(samplesRecorded);
> + if (interpreterProxy->failed()) {
> + return null;
> +@@ -471,4 +476,5 @@ void* SoundPlugin_exports[][3] = {
> +
> +
> + #endif /* ifdef SQ_BUILTIN_PLUGIN */
> ++
> +
> Index: patches/patch-platforms_unix_vm-sound-sndio_Makefile_inc
> ===================================================================
> RCS file: patches/patch-platforms_unix_vm-sound-sndio_Makefile_inc
> diff -N patches/patch-platforms_unix_vm-sound-sndio_Makefile_inc
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-platforms_unix_vm-sound-sndio_Makefile_inc 14 Jan 2020
> 14:59:57 -0000
> @@ -0,0 +1,21 @@
> +$OpenBSD$
> +
> +Index: platforms/unix/vm-sound-sndio/Makefile.inc
> +--- platforms/unix/vm-sound-sndio/Makefile.inc.orig
> ++++ platforms/unix/vm-sound-sndio/Makefile.inc
> +@@ -0,0 +1,15 @@
> ++# Copyright (c) 2019 Mark Hesselink <[email protected]>
> ++#
> ++# Permission to use, copy, modify, and/or distribute this software for any
> ++# purpose with or without fee is hereby granted, provided that the above
> ++# copyright notice and this permission notice appear in all copies.
> ++#
> ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> ANY
> ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> ACTION
> ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
> ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> ++
> ++PLIBS = -lsndio
> Index: patches/patch-platforms_unix_vm-sound-sndio_acinclude_m4
> ===================================================================
> RCS file: patches/patch-platforms_unix_vm-sound-sndio_acinclude_m4
> diff -N patches/patch-platforms_unix_vm-sound-sndio_acinclude_m4
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-platforms_unix_vm-sound-sndio_acinclude_m4 14 Jan 2020
> 14:59:57 -0000
> @@ -0,0 +1,27 @@
> +$OpenBSD$
> +
> +Index: platforms/unix/vm-sound-sndio/acinclude.m4
> +--- platforms/unix/vm-sound-sndio/acinclude.m4.orig
> ++++ platforms/unix/vm-sound-sndio/acinclude.m4
> +@@ -0,0 +1,21 @@
> ++dnl Copyright (c) 2019 Mark Hesselink <[email protected]>
> ++dnl
> ++dnl Permission to use, copy, modify, and/or distribute this software for any
> ++dnl purpose with or without fee is hereby granted, provided that the above
> ++dnl copyright notice and this permission notice appear in all copies.
> ++dnl
> ++dnl THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> ++dnl WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> ++dnl MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> ANY
> ++dnl SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> ++dnl WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> ACTION
> ++dnl OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
> ++dnl CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> ++
> ++AC_MSG_CHECKING([for OpenBSD sndio sound support])
> ++AC_TRY_COMPILE([#include <sndio.h>],[(void)sio_open;],[
> ++ AC_MSG_RESULT([yes])
> ++],[
> ++ AC_MSG_RESULT([no])
> ++ AC_PLUGIN_DISABLE
> ++])
> Index: patches/patch-platforms_unix_vm-sound-sndio_sqUnixSoundSndio_c
> ===================================================================
> RCS file: patches/patch-platforms_unix_vm-sound-sndio_sqUnixSoundSndio_c
> diff -N patches/patch-platforms_unix_vm-sound-sndio_sqUnixSoundSndio_c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-platforms_unix_vm-sound-sndio_sqUnixSoundSndio_c 14 Jan
> 2020 14:59:57 -0000
> @@ -0,0 +1,637 @@
> +$OpenBSD$
> +
> +Index: platforms/unix/vm-sound-sndio/sqUnixSoundSndio.c
> +--- platforms/unix/vm-sound-sndio/sqUnixSoundSndio.c.orig
> ++++ platforms/unix/vm-sound-sndio/sqUnixSoundSndio.c
> +@@ -0,0 +1,631 @@
> ++/* vim: set et sw=4 ts=4:
> ++ * Copyright (c) 2019 Mark Hesselink <[email protected]>
> ++ *
> ++ * Permission to use, copy, modify, and/or distribute this software for any
> ++ * purpose with or without fee is hereby granted, provided that the above
> ++ * copyright notice and this permission notice appear in all copies.
> ++ *
> ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> ANY
> ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> ACTION
> ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
> ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> ++ *
> ++ * Squeak VM sound module for OpenBSD sndio sound system.
> ++ */
> ++
> ++/* Squeak VM uses the following C++-like pseudo-code to play audio:
> ++ *
> ++ * void PlayLoop(Semaphore &playerSemaphore, Condition &readyForData,
> ++ * Buffer &buffer, int stereoFlag)
> ++ * {
> ++ * const int bytesPerFrame = stereoFlag ? 4 : 2;
> ++ * const int startingAt = 0;
> ++ * int frameCount;
> ++ * int framesPlayed;
> ++ *
> ++ * for (;;)
> ++ * {
> ++ * while (
> ++ * (frameCount = primSoundAvailableBytes() / bytesPerFrame) <
> 100)
> ++ * {
> ++ * readyForData.Wait();
> ++ * }
> ++ * framecount = MIN(framecount, buffer.StereoSampleCount());
> ++ * playerSemaphore.Acquire();
> ++ * buffer.Refill();
> ++ * framesPlayed = primSoundPlaySamples(framecount, buffer.Data(),
> ++ * startingAt);
> ++ * playerSemaphore.Release();
> ++ * }
> ++ * }
> ++ *
> ++ *
> ++ * And the following C++-like pseudo-code to record audio:
> ++ *
> ++ * void RecordLoop(Sound &sound, Condition &dataAvailable, Buffer &buffer,
> ++ * int stereoFlag)
> ++ * {
> ++ * int sampleCount;
> ++ * int samplesRecorded = 0;
> ++ * int startingAt = 0;
> ++ *
> ++ * sampleCount = stereoFlag ? buffer.StereoSampleCount() :
> ++ * buffer.MonoSampleCount();
> ++ * for (;;)
> ++ * {
> ++ * if (samplesRecorded == 0)
> ++ * {
> ++ * dataAvailable.Wait();
> ++ * }
> ++ * samplesRecorded = primRecordSamplesInto(buffer.Data(),
> startingAt);
> ++ * startingAt += samplesRecorded;
> ++ * if (startingAt > sampleCount)
> ++ * {
> ++ * sound.Add(buffer);
> ++ * buffer.Reset();
> ++ * startingAt = 0;
> ++ * }
> ++ * }
> ++ * }
> ++ *
> ++ * Running of the play or record loop is preceded by a primStart() and
> ++ * primStartRecording() function call, respectively, to provide the sound
> ++ * driver the required information to configure the sound device.
> ++ *
> ++ * All Squeak objects, such as the `readyForData' and `dataAvailable'
> condition
> ++ * variables or the buffer data arrays, are passed to the sound driver in
> the
> ++ * form of an object-oriented pointer (OOP). This OOP must be converted
> into a
> ++ * C pointer if the sound driver is to access the object directly.
> ++ */
> ++
> ++#include "sq.h"
> ++#include "sqaio.h"
> ++
> ++#include <sys/socket.h>
> ++#include <assert.h>
> ++#include <err.h>
> ++#include <errno.h>
> ++#include <poll.h>
> ++#include <math.h>
> ++#include <sndio.h>
> ++#include <stdio.h>
> ++#include <time.h>
> ++
> ++/*****************************************************************************
> ++ * Constants, Macros & Types
> ++
> *****************************************************************************/
> ++
> ++/* Number of playback buffer entries. Each entry can fit a single
> application
> ++ * buffer rounded up to the nearest block boundary worth of audio frames. */
> ++#define NUM_PBUF 8
> ++/* Number of recording buffer entries. Each entry can fit a single
> application
> ++ * buffer rounded up to the nearest block boundary worth of audio frames. */
> ++#define NUM_RBUF 8
> ++/* Minimum number of blocks that the sndio(7) sound device file handle must
> be
> ++ * able to accept before the sndio(7) sound driver is woken up. */
> ++#define NUM_SBLK 4
> ++
> ++#define SQUEAK_MAX_CHANNELS 2
> ++#define SQUEAK_SAMPLE_SIZE 2 /* bytes */
> ++#define SQUEAK_FRAME_SIZE (SQUEAK_MAX_CHANNELS * SQUEAK_SAMPLE_SIZE)
> ++
> ++#define DPRINTF(format, ...)
> \
> ++ do {
> \
> ++ if (verbose) {
> \
> ++ struct timespec t;
> \
> ++ int rv = clock_gettime(CLOCK_MONOTONIC, &t);
> \
> ++ fprintf(stderr, "%.6f:%s:%d:%s: " format "\n",
> \
> ++ rv == 0 ? ((double)t.tv_sec + (t.tv_nsec / 1e9)) : 0.0,
> \
> ++ __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);
> \
> ++ }
> \
> ++ } while (0)
> ++
> ++#define MIN(a, b) (((a) < (b)) ? (a) : (b))
> ++
> ++struct sndio_play {
> ++ char *devname;
> ++ struct sio_hdl *hdl;
> ++ struct sio_par params;
> ++ int fd;
> ++ double volume;
> ++
> ++ char *buf;
> ++ size_t entrysz;
> ++ size_t head;
> ++ size_t tail;
> ++ size_t offset[NUM_PBUF];
> ++ size_t size[NUM_PBUF];
> ++
> ++ sqInt ready;
> ++ int pending;
> ++};
> ++
> ++struct sndio_rec {
> ++ char *devname;
> ++ struct sio_hdl *hdl;
> ++ struct sio_par params;
> ++ int fd;
> ++
> ++ char *buf;
> ++ size_t entrysz;
> ++ size_t head;
> ++ size_t hoffset;
> ++ size_t hsize;
> ++ size_t tail;
> ++ size_t toffset;
> ++ size_t tsize;
> ++
> ++ sqInt available;
> ++ int pending;
> ++};
> ++
> ++/*****************************************************************************
> ++ * Local Variables
> ++
> *****************************************************************************/
> ++
> ++static struct sndio_play pc = {
> ++ .devname = SIO_DEVANY, .hdl = NULL, .buf = NULL};
> ++
> ++static struct sndio_rec rc = {.devname = SIO_DEVANY, .hdl = NULL, .buf =
> NULL};
> ++
> ++static int verbose = 0;
> ++
> ++/*****************************************************************************
> ++ * Local Function Prototypes
> ++
> *****************************************************************************/
> ++
> ++static sqInt sound_Stop(void);
> ++
> ++static sqInt sound_StopRecording(void);
> ++
> ++/*****************************************************************************
> ++ * Local Functions
> ++
> *****************************************************************************/
> ++
> ++static int init_aio(struct sio_hdl *hdl, aioHandler aio_cb, int flags)
> ++{
> ++ struct pollfd pfd;
> ++
> ++ if ((sio_nfds(hdl) != 1) || !sio_pollfd(hdl, &pfd, 0)) {
> ++ return -1;
> ++ }
> ++ /* It is assumed from this point onward that the number of file
> descriptors
> ++ * used by the sndio(7) audio playback handle remains fixed at 1. */
> ++ aioEnable(pfd.fd, 0, AIO_EXT);
> ++ aioHandle(pfd.fd, aio_cb, flags);
> ++
> ++ return pfd.fd;
> ++}
> ++
> ++static int init_handle(struct sio_hdl **hdl, const char *devname,
> ++ unsigned int mode, struct sio_par *params,
> ++ sqInt frameCount, sqInt samplesPerSec, sqInt
> stereoFlag)
> ++{
> ++ if ((*hdl = sio_open(devname, mode, 1)) == NULL) {
> ++ return 0;
> ++ }
> ++
> ++ sio_initpar(params);
> ++ /* Squeak VM always uses signed 16-bit native endian samples. */
> ++ params->bits = 8 * SQUEAK_SAMPLE_SIZE;
> ++ params->bps = stereoFlag || (mode == SIO_REC) ? SIO_BPS(params->bits)
> ++ : SQUEAK_FRAME_SIZE;
> ++ params->sig = 1;
> ++ params->le = SIO_LE_NATIVE;
> ++ params->msb = 0;
> ++ params->rate = samplesPerSec;
> ++ params->appbufsz = frameCount;
> ++ params->pchan = params->rchan = stereoFlag ? 2 : 1;
> ++ params->xrun = SIO_IGNORE;
> ++ if (!sio_setpar(*hdl, params) || !sio_getpar(*hdl, params)) {
> ++ return 0;
> ++ }
> ++
> ++ return 1;
> ++}
> ++
> ++static void play_cb(int fd, void *user_data, int flags)
> ++{
> ++ struct pollfd pfd;
> ++ size_t nwritten = 0;
> ++ int nfds;
> ++ char *buffer;
> ++
> ++ if (pc.hdl == NULL) {
> ++ return;
> ++ }
> ++
> ++ /* Let the sndio(7) sound driver process messages sent by the sndiod(8)
> ++ * audio server. This is a prerequisite for the sndio(7) sound driver to
> ++ * operate in non-blocking mode.
> ++ *
> ++ * Note: Since the pollfd data structure is filled in based on the
> current
> ++ * messaging state between the sndio(7) sound driver and the sndiod(8)
> ++ * audio server, it must be filled in prior to every poll(2) system
> call.
> ++ */
> ++ if (!sio_pollfd(pc.hdl, &pfd, POLLOUT)) {
> ++ goto ABORT;
> ++ }
> ++ if ((nfds = poll(&pfd, 1, 0)) <= 0) {
> ++ if ((nfds == 0) || (errno == EINTR)) {
> ++ goto EXIT;
> ++ }
> ++ goto ABORT;
> ++ }
> ++ if ((sio_revents(pc.hdl, &pfd) & POLLOUT) == 0) {
> ++ /* Prevent Squeak VM from busy-waiting on asynchronous I/O as much
> as
> ++ * possible when new audio frames can be written to the sndio(7)
> sound
> ++ * driver's file descriptor, but the sndiod(8) audio server is not
> yet
> ++ * ready to receive these new audio frames. */
> ++ DPRINTF("sndiod(8) audio server not ready");
> ++ goto EXIT;
> ++ }
> ++
> ++ if (pc.tail != pc.head) {
> ++ buffer = &pc.buf[pc.tail * pc.entrysz + pc.offset[pc.tail]];
> ++ nwritten = sio_write(pc.hdl, buffer, pc.size[pc.tail]);
> ++ if ((nwritten == 0) && sio_eof(pc.hdl)) {
> ++ goto ABORT;
> ++ }
> ++ pc.offset[pc.tail] += nwritten;
> ++ pc.size[pc.tail] -= nwritten;
> ++ if (pc.size[pc.tail] == 0) {
> ++ pc.tail = (pc.tail + 1) % NUM_PBUF;
> ++ if (!pc.pending) {
> ++ /* Signal Squeak VM that the sndio(7) sound driver can
> accept
> ++ * more audio frames. */
> ++ signalSemaphoreWithIndex(pc.ready);
> ++ pc.pending = 1;
> ++ }
> ++ }
> ++ }
> ++ DPRINTF("phead=%zu ptail=%zu[offset=%zu,size=%zu] nwritten=%zu",
> pc.head,
> ++ pc.tail, pc.offset[pc.tail], pc.size[pc.tail], nwritten);
> ++
> ++EXIT:
> ++ aioHandle(fd, play_cb, flags);
> ++ return;
> ++
> ++ABORT:
> ++ /* REVISIT: Should a warning to the console be issued here? */
> ++ ;
> ++}
> ++
> ++static void record_cb(int fd, void *user_data, int flags)
> ++{
> ++ struct pollfd pfd;
> ++ size_t nread = 0;
> ++ int nfds;
> ++ char *buffer;
> ++
> ++ if (rc.hdl == NULL) {
> ++ return;
> ++ }
> ++
> ++ /* Let the sndio(7) sound driver process messages sent by the sndiod(8)
> ++ * audio server. This is a prerequisite for the sndio(7) sound driver to
> ++ * operate in non-blocking mode.
> ++ *
> ++ * Note: Since the pollfd data structure is filled in based on the
> current
> ++ * messaging state between the sndio(7) sound driver and the sndiod(8)
> ++ * audio server, it must be filled in prior to every poll(2) system
> call.
> ++ */
> ++ if (!sio_pollfd(rc.hdl, &pfd, POLLIN)) {
> ++ goto ABORT;
> ++ }
> ++ if ((nfds = poll(&pfd, 1, 0)) <= 0) {
> ++ if ((nfds == 0) || (errno == EINTR)) {
> ++ goto EXIT;
> ++ }
> ++ goto ABORT;
> ++ }
> ++ if ((sio_revents(rc.hdl, &pfd) & POLLIN) == 0) {
> ++ /* Prevent Squeak VM from busy-waiting on asynchronous I/O as much
> as
> ++ * possible when new audio samples can be read from the sndio(7)
> sound
> ++ * driver's file descriptor, but the sndiod(8) audio server is not
> yet
> ++ * ready to send these new audio samples. */
> ++ DPRINTF("sndiod(8) audio server not ready");
> ++ goto EXIT;
> ++ }
> ++
> ++ if (((rc.head >= rc.tail) && (((rc.tail + NUM_RBUF) - rc.head) > 1)) ||
> ++ ((rc.head < rc.tail) && ((rc.tail - rc.head) > 1))) {
> ++ buffer = &rc.buf[rc.head * rc.entrysz + rc.hoffset];
> ++ nread = sio_read(rc.hdl, buffer, rc.hsize);
> ++ if ((nread == 0) && sio_eof(rc.hdl)) {
> ++ goto ABORT;
> ++ }
> ++ rc.hoffset += nread;
> ++ rc.hsize -= nread;
> ++ if (rc.hsize == 0) {
> ++ rc.head = (rc.head + 1) % NUM_RBUF;
> ++ rc.hoffset = 0;
> ++ rc.hsize = rc.entrysz;
> ++ if (!rc.pending) {
> ++ /* Signal Squeak VM that new audio samples are available. */
> ++ signalSemaphoreWithIndex(rc.available);
> ++ rc.pending = 1;
> ++ }
> ++ }
> ++ }
> ++ DPRINTF("rhead=%zu[offset=%zu,size=%zu] rtail=%zu", rc.head, rc.hoffset,
> ++ rc.hsize, rc.tail);
> ++
> ++EXIT:
> ++ aioHandle(fd, record_cb, flags);
> ++ return;
> ++
> ++ABORT:
> ++ /* REVISIT: Should a warning to the console be issued here? */
> ++ ;
> ++}
> ++
> ++static void volume_cb(void *user_data, unsigned int volume)
> ++{
> ++ pc.volume = ((double)volume) / ((double)SIO_MAXVOL);
> ++ DPRINTF("volume=%u pvolume=%.6f", volume, pc.volume);
> ++}
> ++
> ++static sqInt sound_AvailableSpace(void)
> ++{
> ++ sqInt space = 0;
> ++
> ++ pc.pending = 0;
> ++ if (((pc.head >= pc.tail) && (((pc.tail + NUM_PBUF) - pc.head) > 1)) ||
> ++ ((pc.head < pc.tail) && ((pc.tail - pc.head) > 1))) {
> ++ space = pc.entrysz;
> ++ }
> ++ DPRINTF("space=%d phead=%zu ptail=%zu", space, pc.head, pc.tail);
> ++ return space;
> ++}
> ++
> ++static double sound_GetRecordingSampleRate(void)
> ++{
> ++ /* REVISIT: How best to determine the sound device's recording
> ++ * capabilities? */
> ++ const unsigned int rrate = 44100;
> ++ DPRINTF("rrate=%u", rrate);
> ++ return (double)rrate;
> ++}
> ++
> ++static sqInt sound_InsertSamplesFromLeadTime(sqInt frameCount, sqInt
> dataIndex,
> ++ sqInt samplesOfLeadTime)
> ++{
> ++ DPRINTF("frameCount=%d samplesOfLeadTime=%d", frameCount,
> ++ samplesOfLeadTime);
> ++ return frameCount;
> ++}
> ++
> ++static sqInt sound_PlaySamplesFromAtLength(sqInt frameCount, sqInt
> dataIndex,
> ++ sqInt startingAt)
> ++{
> ++ char *data;
> ++
> ++ data = pointerForOop(dataIndex) + startingAt * SQUEAK_FRAME_SIZE;
> ++ pc.offset[pc.head] = 0;
> ++ pc.size[pc.head] = frameCount * pc.params.bps * pc.params.pchan;
> ++ (void)memcpy(&pc.buf[pc.head * pc.entrysz], data, pc.size[pc.head]);
> ++ pc.head = (pc.head + 1) % NUM_PBUF;
> ++ DPRINTF("frameCount=%d startingAt=%d phead=%zu ptail=%zu", frameCount,
> ++ startingAt, pc.head, pc.tail);
> ++ return frameCount;
> ++}
> ++
> ++static sqInt sound_PlaySilence(void) { return 0; }
> ++
> ++static sqInt sound_RecordSamplesIntoAtLength(sqInt dataIndex, sqInt
> startingAt,
> ++ sqInt bufferSizeInBytes)
> ++{
> ++ sqInt sampleCount = 0;
> ++ size_t nbytes;
> ++ char *buffer;
> ++ char *data;
> ++
> ++ DPRINTF("startingAt=%d bufferSizeInBytes=%d", startingAt,
> ++ bufferSizeInBytes);
> ++ rc.pending = 0;
> ++ if (rc.tail != rc.head) {
> ++ data = pointerForOop(dataIndex) + startingAt * SQUEAK_SAMPLE_SIZE;
> ++ buffer = &rc.buf[rc.tail * rc.entrysz + rc.toffset];
> ++ nbytes =
> ++ MIN(bufferSizeInBytes - startingAt * SQUEAK_SAMPLE_SIZE,
> rc.tsize);
> ++ assert((nbytes % SQUEAK_SAMPLE_SIZE) == 0);
> ++ sampleCount = nbytes / SQUEAK_SAMPLE_SIZE;
> ++ (void)memcpy(data, buffer, nbytes);
> ++ rc.toffset += nbytes;
> ++ rc.tsize -= nbytes;
> ++ if (rc.tsize == 0) {
> ++ rc.tail = (rc.tail + 1) % NUM_RBUF;
> ++ rc.toffset = 0;
> ++ rc.tsize = rc.entrysz;
> ++ }
> ++ }
> ++ return sampleCount;
> ++}
> ++
> ++static void sound_SetVolume(double left, double right)
> ++{
> ++ unsigned int volume;
> ++
> ++ DPRINTF("left=%.6f right=%.6f", left, right);
> ++ volume = (unsigned int)round(MIN(left, right) * SIO_MAXVOL);
> ++ /* REVISIT: How to inform the user that the requested volume change did
> not
> ++ * take effect? */
> ++ (void)sio_setvol(pc.hdl, volume);
> ++}
> ++
> ++static sqInt sound_SetRecordLevel(sqInt level)
> ++{
> ++ DPRINTF("level=%d", level);
> ++ return 1;
> ++}
> ++
> ++static sqInt sound_Start(sqInt frameCount, sqInt samplesPerSec,
> ++ sqInt stereoFlag, sqInt readyForDataIndex)
> ++{
> ++ socklen_t watlen = sizeof(int);
> ++ int watval;
> ++
> ++ DPRINTF("frameCount=%d samplesPerSec=%d stereoFlag=%d", frameCount,
> ++ samplesPerSec, stereoFlag);
> ++
> ++ if (pc.hdl != NULL) {
> ++ /* It is safe to ignore the sound_Stop() return value as the
> function
> ++ * can't fail. */
> ++ (void)sound_Stop();
> ++ }
> ++
> ++ if (!init_handle(&pc.hdl, pc.devname, SIO_PLAY, &pc.params, frameCount,
> ++ samplesPerSec, stereoFlag)) {
> ++ goto ABORT;
> ++ }
> ++
> ++ pc.entrysz = pc.params.appbufsz + pc.params.round - 1;
> ++ pc.entrysz -= pc.entrysz % pc.params.round;
> ++ pc.entrysz *= pc.params.bps * pc.params.pchan;
> ++ if ((pc.buf = reallocarray(pc.buf, NUM_PBUF, pc.entrysz)) == NULL) {
> ++ goto ABORT;
> ++ }
> ++ pc.head = pc.tail = 0;
> ++ pc.ready = readyForDataIndex;
> ++
> ++ if (!sio_onvol(pc.hdl, volume_cb, NULL)) {
> ++ goto ABORT;
> ++ }
> ++ if (!sio_start(pc.hdl)) {
> ++ goto ABORT;
> ++ }
> ++
> ++ if ((pc.fd = init_aio(pc.hdl, play_cb, AIO_W)) == -1) {
> ++ goto ABORT;
> ++ }
> ++
> ++ /* REVISIT: Is it safe to assume that the sndio(7) sound driver always
> ++ * communicates with the sound device via the sndiod(8) audio server? */
> ++ watval = NUM_SBLK * pc.params.round * pc.params.bps * pc.params.pchan;
> ++ if (setsockopt(pc.fd, SOL_SOCKET, SO_SNDLOWAT, &watval, watlen) != 0) {
> ++ goto ABORT;
> ++ }
> ++
> ++ return 1;
> ++
> ++ABORT:
> ++ (void)sound_Stop();
> ++ return 0;
> ++}
> ++
> ++static sqInt sound_StartRecording(sqInt samplesPerSec, sqInt stereoFlag,
> ++ sqInt dataAvailableIndex)
> ++{
> ++ const sqInt frameCount = samplesPerSec / 4;
> ++
> ++ DPRINTF("samplesPerSec=%d stereoFlag=%d", samplesPerSec, stereoFlag);
> ++
> ++ if (rc.hdl != NULL) {
> ++ /* It is safe to ignore the sound_StopRecording() return value as
> the
> ++ * function can't fail. */
> ++ (void)sound_StopRecording();
> ++ }
> ++
> ++ if (!init_handle(&rc.hdl, rc.devname, SIO_REC, &rc.params, frameCount,
> ++ samplesPerSec, stereoFlag)) {
> ++ goto ABORT;
> ++ }
> ++
> ++ rc.available = dataAvailableIndex;
> ++ rc.entrysz = rc.params.appbufsz + rc.params.round - 1;
> ++ rc.entrysz -= rc.entrysz % rc.params.round;
> ++ rc.entrysz *= rc.params.bps * rc.params.pchan;
> ++ if ((rc.buf = reallocarray(rc.buf, NUM_RBUF, rc.entrysz)) == NULL) {
> ++ goto ABORT;
> ++ }
> ++ rc.head = rc.tail = 0;
> ++ rc.hoffset = rc.toffset = 0;
> ++ rc.hsize = rc.tsize = rc.entrysz;
> ++
> ++ if (!sio_start(rc.hdl)) {
> ++ goto ABORT;
> ++ }
> ++
> ++ if ((rc.fd = init_aio(rc.hdl, record_cb, AIO_R)) == -1) {
> ++ goto ABORT;
> ++ }
> ++
> ++ return 1;
> ++
> ++ABORT:
> ++ (void)sound_StopRecording();
> ++ return 0;
> ++}
> ++
> ++static sqInt sound_Stop(void)
> ++{
> ++ DPRINTF("stopping playback");
> ++ if (pc.hdl != NULL) {
> ++ aioDisable(pc.fd);
> ++ sio_close(pc.hdl);
> ++ pc.hdl = NULL;
> ++ free(pc.buf);
> ++ pc.buf = NULL;
> ++ }
> ++ return 1;
> ++}
> ++
> ++static sqInt sound_StopRecording(void)
> ++{
> ++ DPRINTF("stopping recording");
> ++ if (rc.hdl != NULL) {
> ++ aioDisable(rc.fd);
> ++ sio_close(rc.hdl);
> ++ rc.hdl = NULL;
> ++ free(rc.buf);
> ++ rc.buf = NULL;
> ++ }
> ++ return 1;
> ++}
> ++
> ++static void sound_Volume(double *left, double *right)
> ++{
> ++ *left = *right = pc.volume;
> ++ DPRINTF("left=%.6f right=%.6f", *left, *right);
> ++}
> ++
> ++#include "SqSound.h"
> ++
> ++SqSoundDefine(sndio);
> ++
> ++#include "SqModule.h"
> ++
> ++static void *sound_makeInterface(void) { return &sound_sndio_itf; }
> ++
> ++static int sound_parseArgument(int argc, char **argv) { return 0; }
> ++
> ++static void sound_parseEnvironment(void)
> ++{
> ++ const char *errstr;
> ++ char *strval;
> ++
> ++ if ((strval = getenv("SQUEAK_SNDIO_INPUT")) != NULL) {
> ++ rc.devname = strval;
> ++ }
> ++ if ((strval = getenv("SQUEAK_SNDIO_OUTPUT")) != NULL) {
> ++ pc.devname = strval;
> ++ }
> ++ if ((strval = getenv("SQUEAK_SNDIO_LOG_LEVEL")) != NULL) {
> ++ verbose = strtonum(strval, 0, 1, &errstr) != 0;
> ++ if (errstr != NULL) {
> ++ warnx("log level is %s: %s", errstr, strval);
> ++ }
> ++ }
> ++ DPRINTF("pdevname=%s rdevname=%s verbose=%d", pc.devname, rc.devname,
> ++ verbose);
> ++}
> ++
> ++static void sound_printUsage(void) {}
> ++
> ++static void sound_printUsageNotes(void) {}
> ++
> ++SqModuleDefine(sound, sndio);
> Index: patches/patch-platforms_unix_vm_sqUnixMain_c
> ===================================================================
> RCS file:
> /cvs/ports/lang/squeak/vm/patches/patch-platforms_unix_vm_sqUnixMain_c,v
> retrieving revision 1.6
> diff -u -p -r1.6 patch-platforms_unix_vm_sqUnixMain_c
> --- patches/patch-platforms_unix_vm_sqUnixMain_c 6 May 2017 17:15:20
> -0000 1.6
> +++ patches/patch-platforms_unix_vm_sqUnixMain_c 14 Jan 2020 14:59:57
> -0000
> @@ -1,4 +1,5 @@
> -$OpenBSD: patch-platforms_unix_vm_sqUnixMain_c,v 1.6 2017/05/06 17:15:20
> espie Exp $
> +$OpenBSD$
> +
> Index: platforms/unix/vm/sqUnixMain.c
> --- platforms/unix/vm/sqUnixMain.c.orig
> +++ platforms/unix/vm/sqUnixMain.c
> @@ -16,7 +17,15 @@ Index: platforms/unix/vm/sqUnixMain.c
> #undef DEBUG_MODULES
>
> #undef IMAGE_DUMP /* define to enable
> SIGHUP and SIGQUIT handling */
> -@@ -1329,17 +1325,6 @@ int main(int argc, char **argv, char **envp)
> +@@ -698,6 +694,7 @@ static struct moduleDescription moduleDescriptions[]=
> + { &displayModule, "display", "custom" }, /*** NO DEFAULT ***/
> + { &soundModule, "sound", "NAS" }, /*** NO DEFAULT ***/
> + { &soundModule, "sound", "OSS" },
> ++ { &soundModule, "sound", "sndio" },
> + { &soundModule, "sound", "custom" }, /*** NO DEFAULT ***/
> + /* defaults */
> + { &displayModule, "display", "Quartz" },
> +@@ -1329,17 +1326,6 @@ int main(int argc, char **argv, char **envp)
> outOfMemory();
>
> signal(SIGSEGV, sigsegv);
> Index: pkg/PLIST
> ===================================================================
> RCS file: /cvs/ports/lang/squeak/vm/pkg/PLIST,v
> retrieving revision 1.8
> diff -u -p -r1.8 PLIST
> --- pkg/PLIST 11 Sep 2016 16:30:12 -0000 1.8
> +++ pkg/PLIST 14 Jan 2020 14:59:57 -0000
> @@ -1,16 +1,17 @@
> @comment $OpenBSD: PLIST,v 1.8 2016/09/11 16:30:12 ratchov Exp $
> bin/squeak
> lib/squeak/${FULLV}/
> -@bin lib/squeak/${FULLV}/B3DAcceleratorPlugin
> -@bin lib/squeak/${FULLV}/PseudoTTYPlugin
> -@bin lib/squeak/${FULLV}/Squeak3D
> -@bin lib/squeak/${FULLV}/UnixOSProcessPlugin
> -@bin lib/squeak/${FULLV}/XDisplayControlPlugin
> -lib/squeak/${FULLV}/npsqueak.so
> +@so lib/squeak/${FULLV}/B3DAcceleratorPlugin.so
> +@so lib/squeak/${FULLV}/PseudoTTYPlugin.so
> +@so lib/squeak/${FULLV}/Squeak3D.so
> +@so lib/squeak/${FULLV}/UnixOSProcessPlugin.so
> +@so lib/squeak/${FULLV}/XDisplayControlPlugin.so
> +@so lib/squeak/${FULLV}/npsqueak.so
> @bin lib/squeak/${FULLV}/squeak
> -@bin lib/squeak/${FULLV}/vm-display-X11
> -@bin lib/squeak/${FULLV}/vm-display-null
> -@bin lib/squeak/${FULLV}/vm-sound-null
> +@so lib/squeak/${FULLV}/vm-display-X11.so
> +@so lib/squeak/${FULLV}/vm-display-null.so
> +@so lib/squeak/${FULLV}/vm-sound-null.so
> +@so lib/squeak/${FULLV}/vm-sound-sndio.so
> lib/squeak/npsqueakregister
> lib/squeak/npsqueakrun
> @man man/man1/inisqueak.1
>
I'm okay with it. It can only be better than what's currently in.