On Mon, Jun 04, 2018 at 08:37:15PM +0300, Leonid Bobrov wrote:
> But input device is detected, I get crash when trying to
> record my voice.

I installed utox, it doesn't crash with the diff below anymore. The
"Preview" button in the "Audio & Video" settings records my voice.

AFAICS, the interface didn't change, so the recording bits should work
with newer versions of openal as well (I didn't test).

While working on this, I noticed the playback bits need some polishing
as well, but that's for later. You mentioned there are
playback-related crashes, do you have a simple reproducer?

Index: Makefile
===================================================================
RCS file: /cvs/ports/audio/openal/Makefile,v
retrieving revision 1.50
diff -u -p -u -p -r1.50 Makefile
--- Makefile    31 Dec 2017 18:46:26 -0000      1.50
+++ Makefile    5 Jun 2018 05:38:16 -0000
@@ -10,7 +10,7 @@ DISTNAME =    openal-soft-$V
 PKGNAME =      openal-$V
 CATEGORIES =   audio
 SHARED_LIBS =  openal  3.0
-REVISION =     0
+REVISION =     1
 
 HOMEPAGE =     http://kcat.strangesoft.net/openal.html
 
Index: patches/patch-Alc_backends_sndio_c
===================================================================
RCS file: patches/patch-Alc_backends_sndio_c
diff -N patches/patch-Alc_backends_sndio_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-Alc_backends_sndio_c  5 Jun 2018 05:38:16 -0000
@@ -0,0 +1,362 @@
+$OpenBSD$
+
+Index: Alc/backends/sndio.c
+--- Alc/backends/sndio.c.orig
++++ Alc/backends/sndio.c
+@@ -42,16 +42,18 @@ static ALCboolean sndio_load(void)
+ 
+ typedef struct {
+     struct sio_hdl *sndHandle;
++    int mode;
+ 
+     ALvoid *mix_data;
+     ALsizei data_size;
+ 
++    ll_ringbuffer_t *ring;
++
+     volatile int killNow;
+     althrd_t thread;
+ } sndio_data;
+ 
+-
+-static int sndio_proc(void *ptr)
++static int sndio_proc_playback(void *ptr)
+ {
+     ALCdevice *device = ptr;
+     sndio_data *data = device->ExtraData;
+@@ -89,53 +91,22 @@ static int sndio_proc(void *ptr)
+     return 0;
+ }
+ 
+-
+-
+-static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar 
*deviceName)
++static ALCboolean sndio_setparams(ALCdevice *device)
+ {
+-    sndio_data *data;
+-
+-    if(!deviceName)
+-        deviceName = sndio_device;
+-    else if(strcmp(deviceName, sndio_device) != 0)
+-        return ALC_INVALID_VALUE;
+-
+-    data = calloc(1, sizeof(*data));
+-    data->killNow = 0;
+-
+-    data->sndHandle = sio_open(NULL, SIO_PLAY, 0);
+-    if(data->sndHandle == NULL)
+-    {
+-        free(data);
+-        ERR("Could not open device\n");
+-        return ALC_INVALID_VALUE;
+-    }
+-
+-    al_string_copy_cstr(&device->DeviceName, deviceName);
+-    device->ExtraData = data;
+-
+-    return ALC_NO_ERROR;
+-}
+-
+-static void sndio_close_playback(ALCdevice *device)
+-{
+     sndio_data *data = device->ExtraData;
+-
+-    sio_close(data->sndHandle);
+-    free(data);
+-    device->ExtraData = NULL;
+-}
+-
+-static ALCboolean sndio_reset_playback(ALCdevice *device)
+-{
+-    sndio_data *data = device->ExtraData;
+     struct sio_par par;
++    unsigned int nch;
+ 
+     sio_initpar(&par);
+ 
+     par.rate = device->Frequency;
+-    par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1);
++    nch = ((device->FmtChans != DevFmtMono) ? 2 : 1);
+ 
++    if (data->mode & SIO_PLAY)
++      par.pchan = nch;
++    else if (data->mode & SIO_REC)
++      par.rchan = nch;
++
+     switch(device->FmtType)
+     {
+         case DevFmtByte:
+@@ -182,8 +153,10 @@ static ALCboolean sndio_reset_playback(ALCdevice *devi
+         return ALC_FALSE;
+     }
+ 
++    nch = (data->mode & SIO_PLAY) ? par.pchan : par.rchan;
++
+     device->Frequency = par.rate;
+-    device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo);
++    device->FmtChans = ((nch == 1) ? DevFmtMono : DevFmtStereo);
+ 
+     if(par.bits == 8 && par.sig == 1)
+         device->FmtType = DevFmtByte;
+@@ -211,6 +184,47 @@ static ALCboolean sndio_reset_playback(ALCdevice *devi
+     return ALC_TRUE;
+ }
+ 
++static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar 
*deviceName)
++{
++    sndio_data *data;
++
++    if(!deviceName)
++        deviceName = sndio_device;
++    else if(strcmp(deviceName, sndio_device) != 0)
++        return ALC_INVALID_VALUE;
++
++    data = calloc(1, sizeof(*data));
++    data->killNow = 0;
++
++    data->mode = SIO_PLAY;
++    data->sndHandle = sio_open(NULL, data->mode, 0);
++    if(data->sndHandle == NULL)
++    {
++        free(data);
++        ERR("Could not open device\n");
++        return ALC_INVALID_VALUE;
++    }
++
++    al_string_copy_cstr(&device->DeviceName, deviceName);
++    device->ExtraData = data;
++
++    return ALC_NO_ERROR;
++}
++
++static void sndio_close_playback(ALCdevice *device)
++{
++    sndio_data *data = device->ExtraData;
++
++    sio_close(data->sndHandle);
++    free(data);
++    device->ExtraData = NULL;
++}
++
++static ALCboolean sndio_reset_playback(ALCdevice *device)
++{
++    return sndio_setparams(device);
++}
++
+ static ALCboolean sndio_start_playback(ALCdevice *device)
+ {
+     sndio_data *data = device->ExtraData;
+@@ -225,7 +239,7 @@ static ALCboolean sndio_start_playback(ALCdevice *devi
+     data->mix_data = calloc(1, data->data_size);
+ 
+     data->killNow = 0;
+-    if(althrd_create(&data->thread, sndio_proc, device) != althrd_success)
++    if(althrd_create(&data->thread, sndio_proc_playback, device) != 
althrd_success)
+     {
+         sio_stop(data->sndHandle);
+         free(data->mix_data);
+@@ -254,19 +268,190 @@ static void sndio_stop_playback(ALCdevice *device)
+     data->mix_data = NULL;
+ }
+ 
++static int sndio_proc_capture(void *ptr)
++{
++    static char dummy[1024];
++    ALCdevice *device = ptr;
++    sndio_data *data = device->ExtraData;
++    ll_ringbuffer_data_t vec[2], *v;
++    ALsizei frameSize;
++    size_t n, todo, len;
++    char *buf;
+ 
++    SetRTPriority();
++    althrd_setname(althrd_current(), RECORD_THREAD_NAME);
++
++    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
++
++    while(!data->killNow && device->Connected)
++    {
++        todo = device->UpdateSize * frameSize;
++        ll_ringbuffer_get_write_vector(data->ring, vec);
++
++      if (vec[0].len + vec[1].len < device->UpdateSize) {
++
++          /* we're out of free space, drop next block */
++          while (todo > 0) {
++              len = sizeof(dummy);
++              if (len > todo)
++                  len = todo;
++              n = sio_read(data->sndHandle, dummy, len);
++              if (n == 0) {
++                  ERR("sio_read failed\n");
++                  ALCdevice_Lock(device);
++                          aluHandleDisconnect(device);
++                  ALCdevice_Unlock(device);
++              }
++              todo -= n;
++          }
++
++      } else {
++
++          /* record into the ring */
++          v = vec;
++          buf = NULL;
++          len = 0;
++          while (todo > 0) {
++              if (len == 0) {
++                  buf = v->buf;
++                  len = v->len * frameSize;
++                  v++;
++              }
++              n = sio_read(data->sndHandle, buf, len);
++              if (n == 0) {
++                  ERR("sio_read failed\n");
++                  ALCdevice_Lock(device);
++                          aluHandleDisconnect(device);
++                  ALCdevice_Unlock(device);
++              }
++              len -= n;
++              buf += n;
++              todo -= n;
++          }
++          ll_ringbuffer_write_advance(data->ring, device->UpdateSize);
++
++      }
++    }
++
++    return 0;
++}
++
++static ALCenum sndio_open_capture(ALCdevice *device, const ALCchar 
*deviceName)
++{
++    sndio_data *data;
++
++    if(!deviceName)
++        deviceName = sndio_device;
++    else if(strcmp(deviceName, sndio_device) != 0)
++        return ALC_INVALID_VALUE;
++
++    data = calloc(1, sizeof(*data));
++    data->killNow = 0;
++    data->ring = NULL;
++    data->mode = SIO_REC;
++    data->sndHandle = sio_open(NULL, data->mode, 0);
++    if(data->sndHandle == NULL)
++    {
++        free(data);
++        ERR("Could not open device\n");
++        return ALC_INVALID_VALUE;
++    }
++
++    al_string_copy_cstr(&device->DeviceName, deviceName);
++    device->ExtraData = data;
++
++    if (!sndio_setparams(device)) {
++      sio_close(data->sndHandle);
++        free(data);
++        return ALC_INVALID_VALUE;
++    }
++
++    return ALC_NO_ERROR;
++}
++
++static void sndio_close_capture(ALCdevice *device)
++{
++    sndio_data *data = device->ExtraData;
++
++    sio_close(data->sndHandle);
++    free(data);
++    device->ExtraData = NULL;
++}
++
++static void sndio_start_capture(ALCdevice *device)
++{
++    sndio_data *data = device->ExtraData;
++    int frameSize;
++
++    if(!sio_start(data->sndHandle))
++    {
++        ERR("Error starting capture\n");
++        return;
++    }
++
++    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
++    data->ring = ll_ringbuffer_create(device->UpdateSize * 
device->NumUpdates, frameSize);
++    if (!data->ring) {
++        sio_stop(data->sndHandle);
++        return;
++    }
++
++    data->killNow = 0;
++    if(althrd_create(&data->thread, sndio_proc_capture, device) != 
althrd_success)
++    {
++        ll_ringbuffer_free(data->ring);
++        sio_stop(data->sndHandle);
++        return;
++    }
++
++    return;
++}
++
++static void sndio_stop_capture(ALCdevice *device)
++{
++    sndio_data *data = device->ExtraData;
++    int res;
++
++    if(data->killNow)
++        return;
++
++    data->killNow = 1;
++    althrd_join(data->thread, &res);
++
++    if(!sio_stop(data->sndHandle))
++        ERR("Error stopping device\n");
++
++    ll_ringbuffer_free(data->ring);
++    data->ring = NULL;
++}
++
++static ALCenum sndio_captureSamples(ALCdevice *device, ALCvoid *buffer, 
ALCuint samples)
++{
++    sndio_data *data = device->ExtraData;
++
++    ll_ringbuffer_read(data->ring, buffer, samples);
++    return ALC_NO_ERROR;
++}
++
++static ALCuint sndio_availableSamples(ALCdevice *device)
++{
++    sndio_data *data = device->ExtraData;
++
++    return ll_ringbuffer_read_space(data->ring);
++}
++
+ static const BackendFuncs sndio_funcs = {
+     sndio_open_playback,
+     sndio_close_playback,
+     sndio_reset_playback,
+     sndio_start_playback,
+     sndio_stop_playback,
+-    NULL,
+-    NULL,
+-    NULL,
+-    NULL,
+-    NULL,
+-    NULL
++    sndio_open_capture,
++    sndio_close_capture,
++    sndio_start_capture,
++    sndio_stop_capture,
++    sndio_captureSamples,
++    sndio_availableSamples
+ };
+ 
+ ALCboolean alc_sndio_init(BackendFuncs *func_list)
+@@ -289,6 +474,7 @@ void alc_sndio_probe(enum DevProbe type)
+             AppendAllDevicesList(sndio_device);
+             break;
+         case CAPTURE_DEVICE_PROBE:
++            AppendCaptureDeviceList(sndio_device);
+             break;
+     }
+ }

Reply via email to