We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 3705

Summary: [patch] Add capture support to the sndio backend
Product: SDL Reporter: kdrakehp
Component: audioAssignee: Ryan C. Gordon <icculus>
Status: RESOLVED FIXED QA Contact: Sam Lantinga <slouken>
Severity: enhancement    
Priority: P2    
Version: HG 2.1   
Hardware: All   
OS: OpenBSD   
Attachments: Add capture support to the sndio backend
Fixes for the sndio backend
Fixes for the sndio backend
Fix the incorrect check on poll(2)

Description kdrakehp 2017-07-20 01:43:22 UTC
Created attachment 2801 [details]
Add capture support to the sndio backend

The attached patch adds capture support to the sndio backend.

The patch also allows the `OpenDevice' function to accept arbitrary device names.
Comment 1 Sam Lantinga 2017-07-20 17:39:59 UTC
Added, thanks!
https://hg.libsdl.org/SDL/rev/9bdb766ec7e5
Comment 2 Ryan C. Gordon 2017-07-20 18:10:27 UTC
Some minor nitpicks on this patch:

+    while (SNDIO_sio_read(this->hidden->dev, buf, sizeof(buf)) != 0) {
+        /* do nothing */;
+    }

Can this return -1 if there's an error? If so, this will loop forever if a USB audio device is unplugged or whatever, so we should loop while sio_read() > 0.

+        SNDIO_sio_open(devname != NULL ? SIO_DEVANY : devname,

That probably was meant to be "devname == NULL", right?

Also, CaptureFromDevice() needs to block enough to return a value > 0, but it doesn't have to return a full buffer; the calling code knows to loop again to get more data, but it considers a zero return value as a fatal error. I don't know if that simplifies the code much to only block until _something_ is available instead of _enough_ is available, but that option is available to you if it makes things cleaner.

--ryan.
Comment 3 kdrakehp 2017-07-20 20:53:54 UTC
> Can this return -1 if there's an error? If so, this will loop forever if a USB audio
> device is unplugged or whatever, so we should loop while sio_read() > 0.

`sio_read' returns an unsigned value with zero indicating an error.

> That probably was meant to be "devname == NULL", right?

Right, sorry.
Comment 4 kdrakehp 2017-07-20 20:57:01 UTC
Created attachment 2803 [details]
Fixes for the sndio backend
Comment 5 Ryan C. Gordon 2017-07-20 21:02:58 UTC
(In reply to kdrakehp from comment #4)
> Created attachment 2803 [details]
> Fixes for the sndio backend

(this wasn't the patch, can't you attach again? Sorry.)

--ryan.
Comment 6 Ryan C. Gordon 2017-07-20 21:03:42 UTC
> `sio_read' returns an unsigned value with zero indicating an error.

Oh, ok, cool.  :)

--ryan.
Comment 7 kdrakehp 2017-07-20 21:16:53 UTC
Created attachment 2804 [details]
Fixes for the sndio backend
Comment 8 kdrakehp 2017-07-20 21:45:26 UTC
(In reply to Ryan C. Gordon from comment #5)
> (In reply to kdrakehp from comment #4)
> > Created attachment 2803 [details]
> > Fixes for the sndio backend
> 
> (this wasn't the patch, can't you attach again? Sorry.)
> 
> --ryan.

That is odd.  I have added the patch again.
Comment 9 Ryan C. Gordon 2017-07-20 22:22:54 UTC
> That is odd.  I have added the patch again.

Thanks!

This patch is now https://hg.libsdl.org/SDL/rev/dfa9358ae3e0 ...

One last question (just to make sure)...in SNDIO_CaptureFromDevice, this doesn't block at all; this happens in a background thread in SDL, but I assume this is burning the CPU core at full speed waiting for more data to arrive; should we put a sleep in there? (and/or can the device's file descriptor just be set to block, so reads don't return until there is data or an error?).

--ryan.
Comment 10 kdrakehp 2017-07-20 22:45:22 UTC
> One last question (just to make sure)...in SNDIO_CaptureFromDevice, this
> doesn't block at all; this happens in a background thread in SDL, but I
> assume this is burning the CPU core at full speed waiting for more data to
> arrive; should we put a sleep in there? (and/or can the device's file
> descriptor just be set to block, so reads don't return until there is data
> or an error?).
> 
> --ryan.

No, poll(2) waits for an event on the file-descriptor list set by
`sio_pollfd'.  The way I used it in the `CaptureFromDevice' function
waits for the `POLLIN' event to signal that there is data available
to read.  It should only ever execute the loop body once, unless an
interrupt is received.

The `FlushCapture' function is what requires the device to be
non-blocking, because sndio itself does not provide a way to flush
the buffer.

Now that I think about it, I forgot something else.  The comparison
for poll should be ``< 0'' not ``<= 0'', an interrupt would cause
the `CaptureFromDevice' function to incorrectly return zero.

Sorry about that.
Comment 11 kdrakehp 2017-07-20 22:46:40 UTC
Created attachment 2806 [details]
Fix the incorrect check on poll(2)
Comment 12 Ryan C. Gordon 2017-07-21 00:43:19 UTC
> No, poll(2) waits for an event on the file-descriptor list set by

Oh, sorry, you're right. I saw "poll" and ignored the INFTIM argument.

Your poll() fix is now https://hg.libsdl.org/SDL/rev/41d93b7fd207, thanks!

I think this resolves everything, so I'm marking this bug resolved again. Thanks again for working through this with me.  :)

--ryan.