Page MenuHomeFreeBSD

mixer(8): Implement hot-swapping
ClosedPublic

Authored by christos on Aug 9 2024, 6:07 PM.
Tags
None
Referenced Files
F98129536: D46253.id142073.diff
Wed, Oct 2, 10:54 AM
F98039028: D46253.id142130.diff
Wed, Oct 2, 3:17 AM
Unknown Object (File)
Wed, Sep 25, 3:07 AM
Unknown Object (File)
Mon, Sep 23, 6:50 AM
Unknown Object (File)
Sun, Sep 22, 6:44 AM
Unknown Object (File)
Thu, Sep 19, 3:56 AM
Unknown Object (File)
Tue, Sep 10, 4:59 PM
Unknown Object (File)
Sat, Sep 7, 8:25 PM
Subscribers

Details

Summary

Introduce a -V option, which can be used alongside -d (default unit
change), in order to hot-swap devices (i.e switch to them on the fly
without needing to restart the track), in case virtual_oss(8) exists and
is running.

Sponsored by: The FreeBSD Foundation
MFC after: 2 days

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 58976
Build 55863: arc lint + arc unit

Event Timeline

Ideally we could detect the control device automatically, but since there is no way to do this, the best we can do is at least provide it manually. This way we can avoid manually writing the virtual_oss_cmd(8) by hand each time we issue a default unit change and we want to hot-swap at the same time.

Good idea. But it wasn't immediately clear to me how it works and when to use it.

usr.sbin/mixer/mixer.8
58–61

I think we should clarify that this hot-swapping

  • is for use cases where virtual_oss is supposed to be running on the default pcm device
  • is restricted to applications using virtual_oss
  • explain the difference to setting the sound(4) default audio card in the paragraph above

Good idea. But it wasn't immediately clear to me how it works and when to use it.

I know it's kind of tedious and maybe hard to understand at first, but as I said in my initial comment, I don't think we can make this simpler if we don't have a way to know what the virtual_oss control device is, so at least for now this option is a necessary evil.

christos marked an inline comment as done.

Improve -d option paragraph.

Good idea. But it wasn't immediately clear to me how it works and when to use it.

I know it's kind of tedious and maybe hard to understand at first, but as I said in my initial comment, I don't think we can make this simpler if we don't have a way to know what the virtual_oss control device is, so at least for now this option is a necessary evil.

Not only that, there's also the case when the user does not want virtual_oss to run on the (new) default pcm device, in a more static virtual_oss setup for example.

BTW, what happens when a virtual_oss provided pcm device is selected as default device? I don't have much experience with virtual_oss.

Good idea. But it wasn't immediately clear to me how it works and when to use it.

I know it's kind of tedious and maybe hard to understand at first, but as I said in my initial comment, I don't think we can make this simpler if we don't have a way to know what the virtual_oss control device is, so at least for now this option is a necessary evil.

Not only that, there's also the case when the user does not want virtual_oss to run on the (new) default pcm device, in a more static virtual_oss setup for example.

If I understand correctly, you mean what will happen if say, we change the default device to dsp1, but we do not want virtual_oss to use dsp1 as well with this change. In this case we can simply not use the -V option and use just -d normally. Or do you mean something different?

BTW, what happens when a virtual_oss provided pcm device is selected as default device? I don't have much experience with virtual_oss.

mixer(8)'s -d option accepts either an integer representing the sound(4) device unit, or a "pcmX" string (and extracts X), and then calls hw.snd.default_unit, so I don't think there's a problem here. This unit number is also used to form the /dev/dspX string passed as the new playback/recording device to virtual_oss_cmd(8) when the -V option is specified. So the only edge-case I can think of is when the virtual_oss device named to something like dsp1, in which case the device node will be /dev/dsp1. In this case, mixer_set_dunit() will fail because this unit number does not correspond to a sound(4) device, and virtual_oss_cmd will also fail to use this device (from what I can see it only accepts sound(4) devices):

root@freebsd:~ # virtual_oss -T /dev/sndstat -S -C 2 -c 2 -r 48000 -b 16 -s 1024 -f /dev/dsp0 -d dsp1 -t vdsp.ctl &

root@freebsd:~ # virtual_oss_cmd /dev/vdsp.ctl -f /dev/dsp1
virtual_oss: Could not open DSP device '/dev/dsp1': Invalid argument

root@freebsd:~ # mixer -d1 -V /dev/vdsp.ctl:all
mixer: cannot set default unit to 1: Invalid argument
virtual_oss: Could not open DSP device '/dev/dsp1': Invalid argument
usr.sbin/mixer/mixer.c
378

Not sure if we want this or the virtual_oss hot-swapping to come first.

Good idea. But it wasn't immediately clear to me how it works and when to use it.

I know it's kind of tedious and maybe hard to understand at first, but as I said in my initial comment, I don't think we can make this simpler if we don't have a way to know what the virtual_oss control device is, so at least for now this option is a necessary evil.

Not only that, there's also the case when the user does not want virtual_oss to run on the (new) default pcm device, in a more static virtual_oss setup for example.

If I understand correctly, you mean what will happen if say, we change the default device to dsp1, but we do not want virtual_oss to use dsp1 as well with this change. In this case we can simply not use the -V option and use just -d normally. Or do you mean something different?

Yes, I meant that the -V flag is actually a necessity to make it optional, since we neither know which pcm device virtual_oss currently uses, nor whether the user intends to change that. So implementation is fine, I just wanted the man page to explain the use case more explicitly, as in your latest changes.

BTW, what happens when a virtual_oss provided pcm device is selected as default device? I don't have much experience with virtual_oss.

mixer(8)'s -d option accepts either an integer representing the sound(4) device unit, or a "pcmX" string (and extracts X), and then calls hw.snd.default_unit, so I don't think there's a problem here. This unit number is also used to form the /dev/dspX string passed as the new playback/recording device to virtual_oss_cmd(8) when the -V option is specified. So the only edge-case I can think of is when the virtual_oss device named to something like dsp1, in which case the device node will be /dev/dsp1. In this case, mixer_set_dunit() will fail because this unit number does not correspond to a sound(4) device, and virtual_oss_cmd will also fail to use this device (from what I can see it only accepts sound(4) devices):

root@freebsd:~ # virtual_oss -T /dev/sndstat -S -C 2 -c 2 -r 48000 -b 16 -s 1024 -f /dev/dsp0 -d dsp1 -t vdsp.ctl &

root@freebsd:~ # virtual_oss_cmd /dev/vdsp.ctl -f /dev/dsp1
virtual_oss: Could not open DSP device '/dev/dsp1': Invalid argument

root@freebsd:~ # mixer -d1 -V /dev/vdsp.ctl:all
mixer: cannot set default unit to 1: Invalid argument
virtual_oss: Could not open DSP device '/dev/dsp1': Invalid argument

Good, thanks for checking. While we're at it, this only supports one instance of virtual_oss, right?

Also virtual_oss(8) suggests to create a /dev/dsp device to make virtual_oss the default. That overrides the sysctl default unit. I think we should check that and issue a warning with the -d flag, as it has no effect in that case.

usr.sbin/mixer/mixer.c
378

Maybe I'd put mixer_set_dunit() first, including the printf("default unit: ..."). That way there's at least some output in case the execution of virtual_oss_cmd is blocking for whatever reason.

christos marked an inline comment as done.EditedAug 15 2024, 1:01 PM

Good, thanks for checking. While we're at it, this only supports one instance of virtual_oss, right?

A single command yes, because we can pass only a single virtual_oss control device to -V, but if you want you can run the same command with the same -d argument, but different control devices multiple times and it should work fine. The -d option won't take effect because the default unit is already changed but the -V option will change the device virtual_oss uses. Something like this:

# mixer -dpcm1 -V /dev/vdsp1.ctl
# mixer -dpcm1 -V /dev/vdsp2.ctl

Also virtual_oss(8) suggests to create a /dev/dsp device to make virtual_oss the default. That overrides the sysctl default unit. I think we should check that and issue a warning with the -d flag, as it has no effect in that case.

I do not think it overrides the default unit. It turns off hw.snd.basename_clone, so that sound(4) disables access to the /dev/dsp node, in order for virtual_oss to create an actual /dev/dsp device. This is done so applications can still open /dev/dsp as they would normally, but in reality they open the virtual_oss device. It's a hack I guess.

usr.sbin/mixer/mixer.c
378

Yeah, I was thinking the same. Probably better to at least issue the actual default unit change and be more relaxed about whether the virtual_oss_cmd command worked.

Execute mixer_set_dunit() before doing virtual_oss stuff.
Probably final version of the patch.

Also virtual_oss(8) suggests to create a /dev/dsp device to make virtual_oss the default. That overrides the sysctl default unit. I think we should check that and issue a warning with the -d flag, as it has no effect in that case.

I do not think it overrides the default unit. It turns off hw.snd.basename_clone, so that sound(4) disables access to the /dev/dsp node, in order for virtual_oss to create an actual /dev/dsp device. This is done so applications can still open /dev/dsp as they would normally, but in reality they open the virtual_oss device. It's a hack I guess.

As you explain, if /dev/dsp is created by virtual_oss, then setting the hw.snd.default_unit sysctl has no effect. Applications will open the virtual_oss device. Since we're integrating mixer(8) with virtual_oss here, I think we should issue a warning in that case. It's not obvious to the user. Could be done in a separate patch though.

I do not think it overrides the default unit. It turns off hw.snd.basename_clone, so that sound(4) disables access to the /dev/dsp node, in order for virtual_oss to create an actual /dev/dsp device. This is done so applications can still open /dev/dsp as they would normally, but in reality they open the virtual_oss device. It's a hack I guess.

As you explain, if /dev/dsp is created by virtual_oss, then setting the hw.snd.default_unit sysctl has no effect. Applications will open the virtual_oss device. Since we're integrating mixer(8) with virtual_oss here, I think we should issue a warning in that case. It's not obvious to the user. Could be done in a separate patch though.

Well, it has an effect, but it's visible when hw.snd.basename_clone is set again (assuming it is unset in the first place). Also keep in mind that virtual_oss might not necessarily be running as /dev/dsp, in which case hw.snd.basename_clone will not be touched by virtual_oss, so this warning would be false. There can be a case where virtual_oss is running with a device name other than /dev/dsp (and the application has that device open), but uses the default device for playback/recording. In this case, the warning will be false because /dev/dsp will point to the new default device, and virtual_oss will also be re-configured to use the new one as well. I also edited the man page comment about virtual_oss running on the default PCM device (didn't update the diff here). This should work even if it doesn't run on the default.

For example, suppose we have created a virtual_oss device in /dev/foobar, which uses /dev/dsp0 (let's say it's the default) for playback and recording. So in this case, /dev/dsp is still from sound(4) and hw.snd.basename_clone should be set. If we issue a mixer -dpcm1 -V /dev/vdsp.ctl, we will change the default unit to pcm1, and virtual_oss will also switch to /dev/dsp1, even though it's not running as /dev/dsp, and we'll start getting output from pcm1 from the application using that virtual_oss device.

I do not think it overrides the default unit. It turns off hw.snd.basename_clone, so that sound(4) disables access to the /dev/dsp node, in order for virtual_oss to create an actual /dev/dsp device. This is done so applications can still open /dev/dsp as they would normally, but in reality they open the virtual_oss device. It's a hack I guess.

As you explain, if /dev/dsp is created by virtual_oss, then setting the hw.snd.default_unit sysctl has no effect. Applications will open the virtual_oss device. Since we're integrating mixer(8) with virtual_oss here, I think we should issue a warning in that case. It's not obvious to the user. Could be done in a separate patch though.

Well, it has an effect, but it's visible when hw.snd.basename_clone is set again (assuming it is unset in the first place). Also keep in mind that virtual_oss might not necessarily be running as /dev/dsp, in which case hw.snd.basename_clone will not be touched by virtual_oss, so this warning would be false. There can be a case where virtual_oss is running with a device name other than /dev/dsp (and the application has that device open), but uses the default device for playback/recording. In this case, the warning will be false because /dev/dsp will point to the new default device, and virtual_oss will also be re-configured to use the new one as well. I also edited the man page comment about virtual_oss running on the default PCM device (didn't update the diff here). This should work even if it doesn't run on the default.

For example, suppose we have created a virtual_oss device in /dev/foobar, which uses /dev/dsp0 (let's say it's the default) for playback and recording. So in this case, /dev/dsp is still from sound(4) and hw.snd.basename_clone should be set. If we issue a mixer -dpcm1 -V /dev/vdsp.ctl, we will change the default unit to pcm1, and virtual_oss will also switch to /dev/dsp1, even though it's not running as /dev/dsp, and we'll start getting output from pcm1 from the application using that virtual_oss device.

I know all this. How do I rephrase it...

A user issues mixer -d pcm1. Can we agree on the following:

  1. It's very likely that the user wants applications to use /dev/dsp1 as default pcm device now.
  2. If hw.snd.basename_clone isn't set, this doesn't work. One common cause is that virtual_oss has created /dev/dsp.
  3. mixer(8) can check and detect that hw.snd.basename_clone isn't set.

I'd like mixer(8) to print a warning message to the user under those conditions.

Issue warning in case hw.snd.basename_clone is not set.

usr.sbin/mixer/mixer.c
346–348

This is a bit cryptic to inform a normal user. Maybe something like:

warning: hw.snd.basename_clone not set.
The /dev/dsp default audio device for applications is managed externally and does not change with the default unit set here.

Also I think we can omit the check and warning in case the -V flag is used. I'd expect the user to be aware of the situation, and the warning could be confusing.

christos marked an inline comment as done.

Address Florian's comment.

This revision is now accepted and ready to land.Aug 20 2024, 3:30 PM
This revision was automatically updated to reflect the committed changes.