openhab / openhab-addons

Add-ons for openHAB
https://www.openhab.org/
Eclipse Public License 2.0
1.88k stars 3.58k forks source link

[pulseaudio] Audio settings assigned to wrong pulseaudio sink #12631

Closed herrep closed 2 months ago

herrep commented 2 years ago

Expected Behavior

When applying particular audio settings to a particular pulseaudio audio sink, it is expected that these settings will persist until a change is applied. However, under particular circumstances, this expected behavior does not occur.

Current Behavior

In case of having multiple AirPlay audio sinks discovered at the same host, the pulseaudio sound server system may assign different names over time to the same audio sink so that the audio settings are still applied to the audio sink having the same name, but the name of the audio sink alone is not a guarantuee to uniquely identify the same audio sink over time.

As the audio settings are linked to the respective name of the audio sink, the audio settings are suddenly applied to a different audio sink, if the name of the audio sink has been transferred to another audio sink.

Let us assume a music center supporting 4 AirPlay audio sinks. avahi/pulseaudio shows these 4 audio sinks due to discovery via ipv4 and ipv6 as 8 audio sinks as follows:

#device.description #name               #device.string
Schlafzimmer        raop_output.arm-7.local     [192.168.0.160]:5013
Kinderzimmer        raop_output.arm-7.local.2   [192.168.0.160]:5012
Schlafzimmer        raop_output.arm-7.local.3   [2a42:9103:315:7300:135:ffff:fe55:2194]:5013
Kinderzimmer        raop_output.arm-7.local.4   [2a42:9103:315:7300:135:ffff:fe55:2194]:5012
Wohnzimmer      raop_output.arm-7.local.5   [2a42:9103:315:7300:135:ffff:fe55:2194]:5010
Wohnzimmer      raop_output.arm-7.local.6   [192.168.0.160]:5010
Bad         raop_output.arm-7.local.7   [192.168.0.160]:5011
Bad         raop_output.arm-7.local.8   [2a42:9103:315:7300:135:ffff:fe55:2194]:5011

The above 4 audio sinks uniquely identified via device.description are random assigned to a particular name which is static over a few days.

If, for example, a volume of 40 is assigned to the Wohnzimmer audio sink with name raop_output.arm-7.local.5, the volume is correct for the Wohnzimmer audio sink as long as raop_output.arm-7.local.5 identifies the Wohnzimmer audio sink. However, after a few days, it is, for example, the Kinderzimmer audio sink that receives the name raop_output.arm-7.local.5 and then the volume 40 is assigned to the Kinderzimmer audio sink. Therefore, no individual assignment of audio settings is currently possible when using multi-room audio with pulseaudio. It must be expected that a particular audio setting gets overwritten soon by the audio settings of another audio sink.

Workaround and Possible Solution

As a workaround, it would be great if the OpenHAB audio settings for all pulseaudio sink are re-sent again once the pulseaudio addon detects a change in the assignment of device.description / device.string / name. I assume that a proper fix needs to be developed by the pulseaudio sound server team. However, I would like to bring this issue to the attention of OpenHAB users first as I have no particular experience with these software layers.

dalgwen commented 2 years ago

Hello,

For clarity, if someone else than me is bumping onto this thread, I think we could add a link to the other related issue : https://github.com/openhab/openhab-addons/issues/12555 Which is more or less addressed by the not-yet-accepted pull request 12598, whose aims is to allow the use of "description" and others parameters to make the identification of a pulseaudio device more flexible.

This pull request is a prerequisite to the understanding, as it is with this codebase that @herrep expresses this issue.

That said, @herrep, for this issue, when you say the Kinderzimmer audio sink receives the name raop_output.arm-7.local.5 and then the volume 40 is assigned to the Kinderzimmer audio sink, do you mean : 1- The volume channel for Kinderzimmer in openHAB receives an incorrect value ? i.e. it receives 40 although it is not 40 on the pulseaudio server ? OR 2- The pulseaudio device Kinderzimmer on the pulseaudio server receives an incorrect "40" volume command sent by openHAB ? OR 3- the pulseaudio device on the pulseaudio server does not handle well the name switch and Kinderzimmer get the old 40 value from the Wohnzimmer pulseaudio device ?

(Note that 1 could be a consequence of 3)

Another question, if you send to the erroneous volume channel :

I'm still struggling to understand if it is a "pulseaudio side" issue, or an "openHAB side" issue. (If it is a pulseaudio side issue, we can still maybe manage a workaround for your need)

herrep commented 2 years ago

I am quite sure that it is a pure pulseaudio side issue:

That said, @herrep, for this issue, when you say the Kinderzimmer audio sink receives the name raop_output.arm-7.local.5 and then the volume 40 is assigned to the Kinderzimmer audio sink, do you mean :

Answer: 3- the pulseaudio device on the pulseaudio server does not handle well the name switch and Kinderzimmer get the old 40 value from the Wohnzimmer pulseaudio device

The problem is already visible when using the command: pactl -s localhost list sinks

The audio settings of a particular audio sink do not remain at the same physical audio sink over time. Instead, they "move" with the current name of the respective physical audio sink. In the view of the pulseaudio server system, an audio sink is only identified by its name. The pulseaudio server system is simply not aware of the problem that a name is randomly assigned to the audio sinks in case a host provides more than one audio sink. Additionally, the problem does not only concern multiple audio sinks on a host, it already occurs when having both ipv4 and ipv6 enabled in a network. Then you get two pulseaudio sinks for one and the same physical audio sink, eithered connected over ipv4 or ipv6. As it is not guaranteed that ipv4 is always detected first and ipv6 detected second, audio settings will also get lost if the name for the ipv4 audio sink and the ipv6 audio sink flips. Just imagine the case you assign an audio volume to the ipv4 audio sink. Later onwards, the name assignment is different and you get connected to ipv6 using the name that previously connected to the ipv4 audio sink. Then the audio settings applied to ipv4 are not longer valid for the currently assigned ipv6 audio sink. In the case of having only one audio sink per host, but two different network types ipv4/ipv6, you get at least always connected to the correct audio sink. But the issue remains that audio settings are not always correctly applied, as the pulseaudio server system treats both audio sinks as different sinks with different settings stored.

The OpenHAB PulseAudio Addon correctly identifies the current name of a particular pulseaudio sink and sends the volume command to the correct pulseaudio sink. If, in the meantime, the naming of the pulseaudio sinks changed, then the volume remains at the pulseaudio sink having the same name. Unfortunately, it is not the name that correctly identifies the pulseaudio sink.

In view of these observations, I assume that the problem originates from the pulseaudio server system and is probably more precisely related to avahi. According to my very basic understanding of these pieces of software I assume that avahi has problems to assign the same name to the same audio sink over time once there is more than one audio sink per host or more than one network type ipv4/ipv6.

Therefore, when I use the OpenHAB PulseAudio Addon once again and send the correct volume to a pulseaudio sink after a name change, the volume settings arrives at the correct audio sink. This is because the OpenHAB PulseAudio Addon correctly identifies the audio sink.

As the pulseaudio server system does not guarantee that the audio settings are assigned to the correct physical audio sink, it would be required - as a temporary workaroiund - to re-send all audio settings to the currently addressed audio sink to avoid wrong settings to be applied.

dalgwen commented 2 years ago

Thanks for the precisions.

If it is not a bug of the binding (in my understanding, it maybe works as it should, i.e. trusting information from the pulseaudio server), then, I'm not very fond of coding a workaround inside the pulseaudio binding for an external bug. (At least, not for inclusion in the main code, other possibilities can be discussed)

But maybe we could handle it with the help of one simple rule inside openHAB. And if it fixes the issue, it will confirm the supposition that the volume/parameter bug is in the pulseaudio server.

Managing the issue with rules has, however, a prerequisite : that the volume of your sink is purely managed by openHAB. So, is it the case ? Or can other remote control devices or softwares change the volume of the pulseaudio device on the pulseaudio server ?

If openHAB is the sole ruler of the pulseaudio device volume, then we can use a two item pattern.

Then you can use a rule that pushes the volume value from the user one to the technical one with two triggers :

What do you think of this workaround ?

herrep commented 2 years ago

Thank you very much for this discussion of improving the usability of accessing audio sinks.

When generally thinking about the use of remote audio sinks like AirPlay devices in the present discussion, we cannot assume that there is only one party accessing them. I believe the standard case will be that the remote audio sink is idle most of the time, and then, when a particular event occurs, the AirPlay audio sink will be accessed by any party for a while: OpenHAB, a user that streams audio for a while etc.

As a result of this use case, one cannot expect that the audio sink is prepared with correct audio settings. Of course the question arises which instance in OpenHAB will take care of persisting the last audio settings if audio needs to be output.

In my opinion, the most powerful pattern of managing audio settings would be that OpenHAB stores the desired audio setting separately and, prior to outputting audio, temporarily stores the current state of audio settings of the audio sink for restoring them later. Then the desired audio settings are applied to the audio sink and, after the audio output, the temporarily stored audio settings of the audio sink are resumed.

What do you think about this approach and what would be the best pattern as how to realize this functionality?

I do not think that a periodic approach of applying audio settings is recommendable as the audio settings are only required once audio output needs to be processed.

dalgwen commented 2 years ago

In my opinion, the most powerful pattern of managing audio settings would be that OpenHAB stores the desired audio setting separately and, prior to outputting audio, temporarily stores the current state of audio settings of the audio sink for restoring them later. Then the desired audio settings are applied to the audio sink and, after the audio output, the temporarily stored audio settings of the audio sink are resumed.

In fact it is already implemented. When you use the "say" or "play" action, you can optionally specify the volume wanted. https://www.openhab.org/docs/configuration/multimedia.html The volume is restored to the previous value after this. Note that it is not perfect, because there are situations when this volume is not well handled. For example, if you manage to fire a second sound before the first one is ended, the volume "saved" for later restoration could be the one actually used for the first played sound.

I fail to see how this is a solution to the issue you mentioned. But I'm not familiar with the specificity of your situation. Does it cover your use case, or is the bug in the pulseaudio server still a hindrance ?

herrep commented 2 years ago

The already implemented OpenHAB features of specifying a volume level for a particular audio output and restoring the previous volume level reduce the problem.

Nevertheless, the issue remains at pulseaudio server system level that pulseaudio assigns different names to one and the same audio sink over time. Therefore, the restoring of a previous volume level does not correctly work because of issues out of scope of OpenHAB.

dalgwen commented 2 years ago

I'm wondering if you could load the RAOP module manually, instead of automatically letting it do the naming by auto discovery ? The pulseaudio man page says that you could specify the sink name / server when loading.

Maybe you could :

lsiepel commented 2 months ago

A little bit more then two years passed. Is this still an issue with openHAB 4.2.0 and recent pulseaudio server? Is there anything to fix or discuss here?

dalgwen commented 2 months ago

I don't know if pulseaudio server fixed the behaviour with name changing reported by @herrep, but in any case, it seems it is not an issue that we can fix. IHMO, I think we can close this.