[alsa-devel] parameter for pulse device?
Dear ALSA,
In my ~/.asoundrc, I have lines like this:
pcm.mic { type pulse; device "mic" } pcm.monitor { type pulse; device "monitor"; } pcm.music { type pulse; device "music"; }
to make it easier for ALSA-aware programs to input and output via PulseAudio, e.g.:
ecasound -i alsa,mic -o alsa,monitor -etd:...
However, I would like to simplify this and not have to update ~/.asoundrc every time I create a new PulseAudio device. Since ALSA has the ability for PCMs to take a parameter, I thought this might work with the "pulse" PCM and the PulseAudio device name. But I get an "error: Invalid argument" when trying to pass the device name as an argument to the "pulse" PCM:
$ ecasound -o alsa,pulse:music -i some.wav ... ALSA lib conf.c:5014:(snd_config_expand) Unknown parameters music ALSA lib pcm.c:2564:(snd_pcm_open_noupdate) Unknown PCM pulse:music ERROR: Connecting chainsetup failed: "Enabling chainsetup: AUDIOIO-ALSA: ... Unable to open ALSA-device for playback; error: Invalid argument"
Is there some magic with macros that I can use to accomplish this syntax, or can we add the ability for the "pulse" PCM to take a parameter naming the device?
Thanks,
Frederick
On Wed, 04 Sep 2019 18:47:06 +0200, frederik@ofb.net wrote:
Dear ALSA,
In my ~/.asoundrc, I have lines like this:
pcm.mic { type pulse; device "mic" } pcm.monitor { type pulse; device "monitor"; } pcm.music { type pulse; device "music"; }
to make it easier for ALSA-aware programs to input and output via PulseAudio, e.g.:
ecasound -i alsa,mic -o alsa,monitor -etd:...
However, I would like to simplify this and not have to update ~/.asoundrc every time I create a new PulseAudio device. Since ALSA has the ability for PCMs to take a parameter, I thought this might work with the "pulse" PCM and the PulseAudio device name. But I get an "error: Invalid argument" when trying to pass the device name as an argument to the "pulse" PCM:
$ ecasound -o alsa,pulse:music -i some.wav ... ALSA lib conf.c:5014:(snd_config_expand) Unknown parameters music ALSA lib pcm.c:2564:(snd_pcm_open_noupdate) Unknown PCM pulse:music ERROR: Connecting chainsetup failed: "Enabling chainsetup: AUDIOIO-ALSA: ... Unable to open ALSA-device for playback; error: Invalid argument"
Is there some magic with macros that I can use to accomplish this syntax, or can we add the ability for the "pulse" PCM to take a parameter naming the device?
It depends on how pcm.pulse is defined. If it's defined to take an argument, it can work like that. (Or sometimes you may need to pass the argument explicitly like "pulse:{device=mointor}".)
The standard pcm.pulse definition provided in alsa-plugins repo doesn't take the argument, and that can be the reason.
Takashi
On Mon, Sep 09, 2019 at 07:52:24PM +0200, Takashi Iwai wrote:
It depends on how pcm.pulse is defined. If it's defined to take an argument, it can work like that. (Or sometimes you may need to pass the argument explicitly like "pulse:{device=mointor}".)
The standard pcm.pulse definition provided in alsa-plugins repo doesn't take the argument, and that can be the reason.
Thank you Takashi. Would it be easy to change alsa-plugins so that it takes an argument? Is there a chance that this change would be accepted?
If you can point me to the section of code in e.g. "plughw" where argument parsing is done, then I would probably end up modifying alsa-plugins myself, just to simplify what I am doing.
Thanks,
Frederick
On Tue, 2019-09-10 at 10:33 -0700, frederik@ofb.net wrote:
On Mon, Sep 09, 2019 at 07:52:24PM +0200, Takashi Iwai wrote:
It depends on how pcm.pulse is defined. If it's defined to take an argument, it can work like that. (Or sometimes you may need to pass the argument explicitly like "pulse:{device=mointor}".)
The standard pcm.pulse definition provided in alsa-plugins repo doesn't take the argument, and that can be the reason.
Thank you Takashi. Would it be easy to change alsa-plugins so that it takes an argument? Is there a chance that this change would be accepted?
If you can point me to the section of code in e.g. "plughw" where argument parsing is done, then I would probably end up modifying alsa-plugins myself, just to simplify what I am doing.
This commit might be instructive: https://git.alsa-project.org/?p=alsa-lib.git;a=commitdiff;h=3c199a0d199f0fae...
On Tue, 17 Sep 2019 14:51:01 +0200, Tanu Kaskinen wrote:
On Tue, 2019-09-10 at 10:33 -0700, frederik@ofb.net wrote:
On Mon, Sep 09, 2019 at 07:52:24PM +0200, Takashi Iwai wrote:
It depends on how pcm.pulse is defined. If it's defined to take an argument, it can work like that. (Or sometimes you may need to pass the argument explicitly like "pulse:{device=mointor}".)
The standard pcm.pulse definition provided in alsa-plugins repo doesn't take the argument, and that can be the reason.
Thank you Takashi. Would it be easy to change alsa-plugins so that it takes an argument? Is there a chance that this change would be accepted?
If you can point me to the section of code in e.g. "plughw" where argument parsing is done, then I would probably end up modifying alsa-plugins myself, just to simplify what I am doing.
This commit might be instructive: https://git.alsa-project.org/?p=alsa-lib.git;a=commitdiff;h=3c199a0d199f0fae...
Yes, thanks for pointing an example.
Now I took a quick look at the current code, and one remaining problem is that there is no device parameter value corresponding to the default (=NULL). Maybe we should accept the string "default" to be treated as NULL, for example.
Ditto for the server parameter.
thanks,
Takashi
On Tue, 2019-09-17 at 14:55 +0200, Takashi Iwai wrote:
On Tue, 17 Sep 2019 14:51:01 +0200, Tanu Kaskinen wrote:
On Tue, 2019-09-10 at 10:33 -0700, frederik@ofb.net wrote:
On Mon, Sep 09, 2019 at 07:52:24PM +0200, Takashi Iwai wrote:
It depends on how pcm.pulse is defined. If it's defined to take an argument, it can work like that. (Or sometimes you may need to pass the argument explicitly like "pulse:{device=mointor}".)
The standard pcm.pulse definition provided in alsa-plugins repo doesn't take the argument, and that can be the reason.
Thank you Takashi. Would it be easy to change alsa-plugins so that it takes an argument? Is there a chance that this change would be accepted?
If you can point me to the section of code in e.g. "plughw" where argument parsing is done, then I would probably end up modifying alsa-plugins myself, just to simplify what I am doing.
This commit might be instructive: https://git.alsa-project.org/?p=alsa-lib.git;a=commitdiff;h=3c199a0d199f0fae...
Yes, thanks for pointing an example.
Now I took a quick look at the current code, and one remaining problem is that there is no device parameter value corresponding to the default (=NULL). Maybe we should accept the string "default" to be treated as NULL, for example.
Ditto for the server parameter.
Maybe "", i.e. the empty string, would be a good choice for the special string representing NULL? It's not a valid device name or server address, unlike "default", so there can't be any conflicts. Not that "default" is very likely to cause conflicts either.
On Tue, 17 Sep 2019 15:14:53 +0200, Tanu Kaskinen wrote:
On Tue, 2019-09-17 at 14:55 +0200, Takashi Iwai wrote:
On Tue, 17 Sep 2019 14:51:01 +0200, Tanu Kaskinen wrote:
On Tue, 2019-09-10 at 10:33 -0700, frederik@ofb.net wrote:
On Mon, Sep 09, 2019 at 07:52:24PM +0200, Takashi Iwai wrote:
It depends on how pcm.pulse is defined. If it's defined to take an argument, it can work like that. (Or sometimes you may need to pass the argument explicitly like "pulse:{device=mointor}".)
The standard pcm.pulse definition provided in alsa-plugins repo doesn't take the argument, and that can be the reason.
Thank you Takashi. Would it be easy to change alsa-plugins so that it takes an argument? Is there a chance that this change would be accepted?
If you can point me to the section of code in e.g. "plughw" where argument parsing is done, then I would probably end up modifying alsa-plugins myself, just to simplify what I am doing.
This commit might be instructive: https://git.alsa-project.org/?p=alsa-lib.git;a=commitdiff;h=3c199a0d199f0fae...
Yes, thanks for pointing an example.
Now I took a quick look at the current code, and one remaining problem is that there is no device parameter value corresponding to the default (=NULL). Maybe we should accept the string "default" to be treated as NULL, for example.
Ditto for the server parameter.
Maybe "", i.e. the empty string, would be a good choice for the special string representing NULL? It's not a valid device name or server address, unlike "default", so there can't be any conflicts. Not that "default" is very likely to cause conflicts either.
Yeah, that sounds feasible. Then the rest is just coding ;)
thanks,
Takashi
Thank you for the tips.
I don't know if my input is still needed, but I figured out from looking at some of the syntax you linked to that I can put this in ~/.asoundrc and it does the job (this is what I had had in mind when I asked about "magic with macros", it is somewhat advanced for me):
pcm.!pulse { @args [ DEV ] @args.DEV { type string default "default" } type pulse; device $DEV }
Now I can set up a filter like this:
ecasound -i alsa,pulse:mic -o alsa,pulse:monitor
Is something like this going into the alsa-plugins repo?
Thanks,
Frederick
On Tue, Sep 17, 2019 at 03:17:49PM +0200, Takashi Iwai wrote:
On Tue, 17 Sep 2019 15:14:53 +0200, Tanu Kaskinen wrote:
On Tue, 2019-09-17 at 14:55 +0200, Takashi Iwai wrote:
On Tue, 17 Sep 2019 14:51:01 +0200, Tanu Kaskinen wrote:
On Tue, 2019-09-10 at 10:33 -0700, frederik@ofb.net wrote:
On Mon, Sep 09, 2019 at 07:52:24PM +0200, Takashi Iwai wrote:
It depends on how pcm.pulse is defined. If it's defined to take an argument, it can work like that. (Or sometimes you may need to pass the argument explicitly like "pulse:{device=mointor}".)
The standard pcm.pulse definition provided in alsa-plugins repo doesn't take the argument, and that can be the reason.
Thank you Takashi. Would it be easy to change alsa-plugins so that it takes an argument? Is there a chance that this change would be accepted?
If you can point me to the section of code in e.g. "plughw" where argument parsing is done, then I would probably end up modifying alsa-plugins myself, just to simplify what I am doing.
This commit might be instructive: https://git.alsa-project.org/?p=alsa-lib.git;a=commitdiff;h=3c199a0d199f0fae...
Yes, thanks for pointing an example.
Now I took a quick look at the current code, and one remaining problem is that there is no device parameter value corresponding to the default (=NULL). Maybe we should accept the string "default" to be treated as NULL, for example.
Ditto for the server parameter.
Maybe "", i.e. the empty string, would be a good choice for the special string representing NULL? It's not a valid device name or server address, unlike "default", so there can't be any conflicts. Not that "default" is very likely to cause conflicts either.
Yeah, that sounds feasible. Then the rest is just coding ;)
thanks,
Takashi
On Thu, 2019-09-19 at 14:12 -0700, frederik@ofb.net wrote:
Thank you for the tips.
I don't know if my input is still needed, but I figured out from looking at some of the syntax you linked to that I can put this in ~/.asoundrc and it does the job (this is what I had had in mind when I asked about "magic with macros", it is somewhat advanced for me):
pcm.!pulse { @args [ DEV ] @args.DEV { type string default "default" } type pulse; device $DEV }
Now I can set up a filter like this:
ecasound -i alsa,pulse:mic -o alsa,pulse:monitor
Is something like this going into the alsa-plugins repo?
I'm sure something like this will be accepted if you submit a patch. I got the impression that Takashi isn't willing to write the patch himself, and nor am I, so you're in the best position to make this happen.
Note that
default "default"
doesn't do the intended thing with the current pcm_pulse.c code. With the current code the plugin will request PulseAudio to use a device named "default", which most likely won't exist and playback or recording will fail. The plugin code needs to pass NULL as the device name to pa_stream_connect_playback() and pa_stream_connect_record() when it detects that the default device is requested, so you'll need to modify pcm_pulse.c in order to make this work. Instead of "default" as the special string in the configuration, I suggested using "".
On Fri, 20 Sep 2019 09:35:59 +0200, Tanu Kaskinen wrote:
On Thu, 2019-09-19 at 14:12 -0700, frederik@ofb.net wrote:
Thank you for the tips.
I don't know if my input is still needed, but I figured out from looking at some of the syntax you linked to that I can put this in ~/.asoundrc and it does the job (this is what I had had in mind when I asked about "magic with macros", it is somewhat advanced for me):
pcm.!pulse { @args [ DEV ] @args.DEV { type string default "default" } type pulse; device $DEV }
Now I can set up a filter like this:
ecasound -i alsa,pulse:mic -o alsa,pulse:monitor
Is something like this going into the alsa-plugins repo?
I'm sure something like this will be accepted if you submit a patch. I got the impression that Takashi isn't willing to write the patch himself, and nor am I, so you're in the best position to make this happen.
I have a test patch but had no chance to test the stuff at all currently as I am (and will be for the next few weeks) traveling.
Note that
default "default"
doesn't do the intended thing with the current pcm_pulse.c code. With the current code the plugin will request PulseAudio to use a device named "default", which most likely won't exist and playback or recording will fail. The plugin code needs to pass NULL as the device name to pa_stream_connect_playback() and pa_stream_connect_record() when it detects that the default device is requested, so you'll need to modify pcm_pulse.c in order to make this work. Instead of "default" as the special string in the configuration, I suggested using "".
Below is the totally untested patch (even not build-tested!) If anyone interested, feel free to cook it.
thanks,
Takashi
--- diff --git a/pulse/50-pulseaudio.conf b/pulse/50-pulseaudio.conf index 62da207af9ca..916258d942af 100644 --- a/pulse/50-pulseaudio.conf +++ b/pulse/50-pulseaudio.conf @@ -1,7 +1,13 @@ # Add a specific named PulseAudio pcm and ctl (typically useful for testing)
pcm.pulse { + @args [ DEVICE ] + @args.DEVICE { + type string + default "" + } type pulse + device $DEVICE hint { show { @func refer diff --git a/pulse/ctl_pulse.c b/pulse/ctl_pulse.c index fbb6eae2ec76..9b820fd04b15 100644 --- a/pulse/ctl_pulse.c +++ b/pulse/ctl_pulse.c @@ -664,6 +664,8 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &server) < 0) { SNDERR("Invalid type for %s", id); return -EINVAL; + } else if (!*server) { + server = NULL; } continue; } @@ -671,6 +673,8 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &device) < 0) { SNDERR("Invalid type for %s", id); return -EINVAL; + } else if (!*device) { + device = NULL; } continue; } @@ -678,6 +682,8 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &source) < 0) { SNDERR("Invalid type for %s", id); return -EINVAL; + } else if (!*source) { + source = NULL; } continue; } @@ -685,6 +691,8 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &sink) < 0) { SNDERR("Invalid type for %s", id); return -EINVAL; + } else if (!*sink) { + sink = NULL; } continue; } diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c index 283174357e8b..869c9b674c6b 100644 --- a/pulse/pcm_pulse.c +++ b/pulse/pcm_pulse.c @@ -1069,6 +1069,8 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &server) < 0) { SNDERR("Invalid type for %s", id); return -EINVAL; + } else if (!*server) { + server = NULL; } continue; } @@ -1076,6 +1078,8 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &device) < 0) { SNDERR("Invalid type for %s", id); return -EINVAL; + } else if (!*device) { + device = NULL; } continue; } @@ -1091,6 +1095,8 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &fallback_name) < 0) { SNDERR("Invalid value for %s", id); return -EINVAL; + } else if (!*fallback_name) { + fallback_name = NULL; } continue; }
Dear Takashi,
I tested your patch, after commenting some lines in my ~/.asoundrc, and I can confirm that it works. I can now specify a pulse device to 'ecasound':
ecasound -o alsa,pulse:music -i song.wav
and when I do it with no "DEVICE" argument, then it outputs to the sink defined by "pacmd set-default-sink":
ecasound -o alsa,pulse -i song.wav
I guess this only exercises one of the cases in your patch where the empty string is recognized as NULL:
+ } else if (!*device) { + device = NULL;
Let me know if you want me to do more testing, and apologies for the long delay in my reply.
Thanks,
Frederick
On Fri, Sep 20, 2019 at 09:44:19AM +0200, Takashi Iwai wrote:
On Fri, 20 Sep 2019 09:35:59 +0200, Tanu Kaskinen wrote:
On Thu, 2019-09-19 at 14:12 -0700, frederik@ofb.net wrote:
Thank you for the tips.
I don't know if my input is still needed, but I figured out from looking at some of the syntax you linked to that I can put this in ~/.asoundrc and it does the job (this is what I had had in mind when I asked about "magic with macros", it is somewhat advanced for me):
pcm.!pulse { @args [ DEV ] @args.DEV { type string default "default" } type pulse; device $DEV }
Now I can set up a filter like this:
ecasound -i alsa,pulse:mic -o alsa,pulse:monitor
Is something like this going into the alsa-plugins repo?
I'm sure something like this will be accepted if you submit a patch. I got the impression that Takashi isn't willing to write the patch himself, and nor am I, so you're in the best position to make this happen.
I have a test patch but had no chance to test the stuff at all currently as I am (and will be for the next few weeks) traveling.
Note that
default "default"
doesn't do the intended thing with the current pcm_pulse.c code. With the current code the plugin will request PulseAudio to use a device named "default", which most likely won't exist and playback or recording will fail. The plugin code needs to pass NULL as the device name to pa_stream_connect_playback() and pa_stream_connect_record() when it detects that the default device is requested, so you'll need to modify pcm_pulse.c in order to make this work. Instead of "default" as the special string in the configuration, I suggested using "".
Below is the totally untested patch (even not build-tested!) If anyone interested, feel free to cook it.
thanks,
Takashi
diff --git a/pulse/50-pulseaudio.conf b/pulse/50-pulseaudio.conf index 62da207af9ca..916258d942af 100644 --- a/pulse/50-pulseaudio.conf +++ b/pulse/50-pulseaudio.conf @@ -1,7 +1,13 @@ # Add a specific named PulseAudio pcm and ctl (typically useful for testing)
pcm.pulse {
- @args [ DEVICE ]
- @args.DEVICE {
type string
default ""
- } type pulse
- device $DEVICE hint { show { @func refer
diff --git a/pulse/ctl_pulse.c b/pulse/ctl_pulse.c index fbb6eae2ec76..9b820fd04b15 100644 --- a/pulse/ctl_pulse.c +++ b/pulse/ctl_pulse.c @@ -664,6 +664,8 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &server) < 0) { SNDERR("Invalid type for %s", id); return -EINVAL;
} else if (!*server) {
}server = NULL; } continue;
@@ -671,6 +673,8 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &device) < 0) { SNDERR("Invalid type for %s", id); return -EINVAL;
} else if (!*device) {
}device = NULL; } continue;
@@ -678,6 +682,8 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &source) < 0) { SNDERR("Invalid type for %s", id); return -EINVAL;
} else if (!*source) {
}source = NULL; } continue;
@@ -685,6 +691,8 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &sink) < 0) { SNDERR("Invalid type for %s", id); return -EINVAL;
} else if (!*sink) {
}sink = NULL; } continue;
diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c index 283174357e8b..869c9b674c6b 100644 --- a/pulse/pcm_pulse.c +++ b/pulse/pcm_pulse.c @@ -1069,6 +1069,8 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &server) < 0) { SNDERR("Invalid type for %s", id); return -EINVAL;
} else if (!*server) {
}server = NULL; } continue;
@@ -1076,6 +1078,8 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &device) < 0) { SNDERR("Invalid type for %s", id); return -EINVAL;
} else if (!*device) {
}device = NULL; } continue;
@@ -1091,6 +1095,8 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse) if (snd_config_get_string(n, &fallback_name) < 0) { SNDERR("Invalid value for %s", id); return -EINVAL;
} else if (!*fallback_name) {
}fallback_name = NULL; } continue;
On Tue, 15 Oct 2019 17:52:02 +0200, frederik@ofb.net wrote:
Dear Takashi,
I tested your patch, after commenting some lines in my ~/.asoundrc, and I can confirm that it works. I can now specify a pulse device to 'ecasound':
ecasound -o alsa,pulse:music -i song.wav
and when I do it with no "DEVICE" argument, then it outputs to the sink defined by "pacmd set-default-sink":
ecasound -o alsa,pulse -i song.wav
I guess this only exercises one of the cases in your patch where the empty string is recognized as NULL:
} else if (!*device) {
device = NULL;
Let me know if you want me to do more testing, and apologies for the long delay in my reply.
OK, good to hear. Now I applied the patch to git repo.
thanks,
Takashi
Dear all,
I am involved in a project which will use different kernel versions along the way, first 4.14, 4.19, 5.3 etc.
How can I know the differences in ALSA, besides comparing files ? How to get the ALSA version in Linux kernel ?
Thanks a lot,
Xinhui,
On Thu, 12 Sep 2019 17:42:37 +0200, xinhui zhou wrote:
Dear all,
I am involved in a project which will use different kernel versions
along the way, first 4.14, 4.19, 5.3 etc.
How can I know the differences in ALSA, besides comparing files ?
How to get the ALSA version in Linux kernel ?
There is no "ALSA version" any longer in the kernel side. The protocol is kept in backward-compatible way, and a new protocol is checked via each protocol version number ioctl.
Takashi
Dear all ,
The tutorial below states that ""Each card device can have up to four pcm instances" https://www.kernel.org/doc/html/v4.19/sound/kernel-api/writing-an-alsa-drive... https://www.google.com/url?q=https://www.kernel.org/doc/html/v4.19/sound/kernel-api/writing-an-alsa-driver.html%23pcm-interface&sa=D&source=hangouts&ust=1573928998988000&usg=AFQjCNGmZgiENmLej2aBTQvp-tspn3u8sg
I am getting confused with the number '4' . I thought we can add 8 pcm device files by default. By setting 'CONFIG_SND_DYNAMIC_MINORS=y' , we can have more than 8 pcm device files. Does that tutorial mean only 4 pcm devices running at the same time ?
Thanks a lot,
Xinhui,
participants (4)
-
frederik@ofb.net
-
Takashi Iwai
-
Tanu Kaskinen
-
xinhui zhou