On Thu, Dec 09, 2021 at 11:29:04PM +0000, Klemens Nanni wrote:
> On Thu, Dec 09, 2021 at 10:21:56AM +0100, Alexandre Ratchov wrote:
> > On Wed, Dec 08, 2021 at 10:30:08PM +0000, Klemens Nanni wrote:
> > > Following https://www.openbsd.org/faq/faq13.html#usbaudio and reading
> > > sndiod(8)'s
> > > 
> > >   -F device
> > >           Specify an alternate device to use.  If it doesn't work, the one
> > >           given with the last -f or -F options will be used.  For 
> > > instance,
> > >           specifying a USB device following a PCI device allows sndiod to
> > >           use the USB one preferably when it's connected and to fall back
> > >           to the PCI one when it's disconnected.  Alternate devices may be
> > >           switched with the server.device control of the sndioctl(1)
> > >           utility.
> > > 
> > > I configured things as follows in order to play audio via USB and
> > > fall back to internal sound if USB is not available:
> > > 
> > >   $ rcctl get sndiod flags
> > >   -f rsnd/0 -F rsnd/1
> > > 
> > > Plugging in an USB headset and restarting sndiod or forcing the device
> > > with `sndioctl server.device=1' then plays sound via USB.
> > > 
> > > Unplugging the device makes playback fall back to internal sound.
> > > 
> > > But plugging USB back in does not prefer USB to internal as I'd expect
> > > now. I am currently resorting to the following hotplugd(8) script to
> > > always select the USB sound device whenever I plug it in:
> > > 
> > >   #!/bin/ksh
> > >   set -Cefu -o pipefail
> > > 
> > >   readonly DEVCLASS=$1 DEVNAME=$2
> > >   typeset -i devid
> > > 
> > >   case "${DEVCLASS}-${DEVNAME}" in
> > >   0-audio*)       # switch sndio(4) to USB headset when plugging it in
> > >           devid=${DEVNAME#audio}
> > >           sndioctl server.device=${devid}
> > >           ;;
> > >   esac
> > > 
> > 
> > IFAIU, audio devices always match the audio[0-9] pattern, so testing
> > the device class is not necessary, is it? FWIW, I use a similar
> > script.
> 
> I do it that way because /etc/hotplug/attach handles *all* events, so
> extending it with other cases where DEVCLASS matters would be obvious
> and audio(4) does not have to be treated specially.
> 
> > > I'd expect sndiod to *always* use USB whenever possible.
> > > 
> > > Is this uni-directional behaviour of sndiod intentional/by-design?
> > 
> > sndiod doesn't use directly hotplug(4), so it can't obtain by itself a
> > notification when a new device is plugged in order to switch to
> > it. Using hotplugd(8) is the right way to make audio hotplug work,
> > both daemons complete each other.
> 
> Alright, hotplugd it is, then.
> 
> > When sndiod needs the audio device (i.e. when the first client
> > connects), it will try all alternate devices (reverse -F options
> > order, the USB headset is first in your case). This gives a false
> > impression of hotplug support (indeed, you plug the USB headset, start
> > an audio player and it just works!). But that's just a side effect of
> > device priority/fail-over: if the internal device is already open when
> > you plug the USB headset, sndiod won't switch to it until it needs to
> > reopen the device.
> > 
> > Certain programs (including browsers), tend to keep the device open
> > even when they remain silent. So when actual playback starts sndiod
> > doesn't need to open a device and doesn't "see" the new USB headset. I
> > guess that's what happens on your system, but hotplugd(8) handles
> > this.
> > 
> > When devices are unplugged, we don't need hotplug because the device
> > stops working (input/output error) and sndiod switch to the next one
> > of the fail-over list.
> > 
> > > If so, can we clarify the manual?
> > 
> > Sure. While -F option description seems exact, maybe we need an extra
> > paragraph or FAQ entry to explain how to use it with other tools like
> > hotplugd and sndioctl. What about this wording?
> 
> Exact, but it could be clearer about the uni-directional fallack
> semantic, which is only relevant upon startup.  Then I wouldn't think
> it switches back and forth at runtime.
> 
> > HOT-PLUG SUPPORT
> >      If a device is unplugged while in use, sndiod will attempt to switch to
> >      one of the alternate devices (-F), if any.  This is seamless to 
> > programs
> >      connected to sndiod.
> > 
> >      Later, when the device is connected again, the server.device control of
> >      the sndioctl(1) utility could be used to switch back to it, without the
> >      need to restart all audio programs.  This last step could be automated
> >      using hotplugd(8).  For instance, if sndiod is started with:
> > 
> >            $ sndiod -f rsnd/0 -F rsnd/1 -F rsnd/2 -F rsnd/3
> > 
> >      then, the following hotplugd(8) attach script could be used to
> >      automatically switch to the last connected device:
> > 
> >            #!/bin/sh
> > 
> >            DEVNAME=$2
> > 
> >            case $DEVNAME in
> >            audio[0-3])
> >                    sndioctl server.device=${DEVNAME#audio}
> >                    ;;
> >            esac
> 
> This is clear and gets users going in no time.
> With this I would not even have looked at the FAQ (which follows release
> and not -current, which can be a problem).
> 
> > Any opinions where to put such information?
> 
> As jmc suggests, this belongs into sndiod(8), imho.
> 
> 
> Here's my `-F' tweak plus your idea put split into a new section
> HOT PLUGGING (hotplug(4)/hotplugd(8) verbiage) that tries to explain
> sndiod's (missing) internal hotplug semantics and is nicely followed by
> an example on how to do so.
> 
> I try to clarify the difference between (failure induced) fallback from
> gone devices and nonexistent opportunistic switching to new ones.

So we've concluded that the hotplpugging framework needs work, fine.

I'd still like to improve sndiod(8) regarding its own behaviour.

How about the same diff modulo hotplug referencing/examples?
This helps me understand `-f' and `-F' usage better.

Feedback? Objections? OK?

Index: sndiod.8
===================================================================
RCS file: /cvs/src/usr.bin/sndiod/sndiod.8,v
retrieving revision 1.11
diff -u -p -r1.11 sndiod.8
--- sndiod.8    16 Jul 2021 15:05:58 -0000      1.11
+++ sndiod.8    17 Dec 2021 19:02:21 -0000
@@ -185,7 +185,7 @@ Only the signedness and the precision ar
 Examples:
 .Va u8 , s16le , s24le3 , s24le4lsb .
 .It Fl F Ar device
-Specify an alternate device to use.
+Specify a preferred device to use on startup.
 If it doesn't work, the one given with the last
 .Fl f
 or
@@ -528,6 +528,24 @@ behave normally, while streams connected
 wait for the MMC start signal and start synchronously.
 Regardless of which device a stream is connected to,
 its playback volume knob is exposed.
+.Sh HOT PLUGGING
+.Nm
+If preferred devices specified with
+.Fl F
+are unavailable at startup or detach at runtime,
+.Nm
+will attempt to seamlessly fall back to the last device specified.
+.Pp
+.Nm
+will not automatically switch to specified devices that attach at runtime.
+Instead,
+.Xr sndioctl 1
+must be used to change the
+.Va server.device
+control.
+.Pp
+.Xr hotplugd 8
+can be used to implement seamless switching at runtime.
 .Sh EXAMPLES
 Start server using default parameters, creating an
 additional sub-device for output to channels 2:3 only (rear speakers

Reply via email to