[pulseaudio-discuss] RFC: Public API for managing nodes

David Henningsson david.henningsson at canonical.com
Tue Aug 6 05:42:30 PDT 2013


On 08/06/2013 02:30 PM, Tanu Kaskinen wrote:
> On Tue, 2013-08-06 at 13:26 +0200, David Henningsson wrote:
>> On 08/05/2013 01:37 PM, Tanu Kaskinen wrote:
>>> On Wed, 2013-07-17 at 12:26 +0200, David Henningsson wrote:
>>>> On 07/17/2013 11:22 AM, Tanu Kaskinen wrote:
>>>>> On Wed, 2013-07-17 at 09:27 +0200, David Henningsson wrote:
>>>>>> On 07/16/2013 03:20 PM, Tanu Kaskinen wrote:
>>>>>>> Yes, there can be both an explicit and a default connection between two
>>>>>>> nodes, or it can be also thought as being one connection that is both
>>>>>>> explicit and default. I don't know what is a better way to think about
>>>>>>> it, but perhaps it doesn't matter anyway.
>>>>>>
>>>>>> I would prefer the latter way. I would then see "default" and "explicit"
>>>>>> as a property of the edge.
>>>>>
>>>>> I agree about that, at a conceptual level. Would you perhaps like to
>>>>> have it this way also at the code level, i.e. have connection objects
>>>>> with "default" and "explicit" fields instead of storing the information
>>>>> in the nodes?
>>>>
>>>> Good question. Actually one option could be to store the connections as 
>>>> global list-like matrix instead of lists on the individual node objects. 
>>>> After all, you'll need the connection on both sides, and unless you want 
>>>> to duplicate information, you'll have to do a global search on one of 
>>>> the sides anyway. Since the number of nodes < 100, I don't think this 
>>>> would matter from a performance standpoint.
>>>>
>>>> You would end up with a global list with entries looking something like:
>>>>
>>>> struct pa_node_connection_t {
>>>>    pa_node *from_node;
>>>>    pa_node *to_node;
>>>>    bool default;
>>>
>>> A single "default" boolean isn't enough. A connection may be part of
>>> both endpoints' default routing, or just one. It's necessary to
>>> differentiate between the different cases, because disabling one node's
>>> default connections may not remove the connection, if it's also a
>>> default connection of the other node.
>>
>> I'm not sure I know the background enough to understand why you need to
>> store whether the connection is done on the basis on a request from the
>> from_node or to_node (?), but at this point, sure, we can have a bool
>> from_default and a bool to_default if that solves your problem.
> 
> When you proposed the struct, you assumed that blacklisting would be
> available, and in that case you might not need to know the origin of the
> default connection. I failed to take this into account when I said that
> a single boolean isn't enough.
> 
> If default connections are removed by disabling all default routing for
> a node, as opposed to blacklisting certain connections, then you need to
> know which node you need to request to disable its default routing in
> order to get rid of the default connection.
> 
>>>>>>> What operations do you mean? Moving or removing a default connection is
>>>>>>> not supported as such, but if the client tries that anyway, we can
>>>>>>> implicitly convert the connection to an explicit one and disable default
>>>>>>> connections, or we can require the client to do these operations
>>>>>>> explicitly, but I think the latter would be too inconvenient for the
>>>>>>> client.
>>>>>>
>>>>>> Ok, I think I didn't read the proposal well enough. Having done that, I
>>>>>> understand that you're suggesting a global switch "default connections
>>>>>> on/off" only. Or is it a per-node switch?
>>>>>
>>>>> It is a per-node switch.
>>>>>
>>>>>> I have another idea that might be worth considering: how about that the
>>>>>> "explicit" layer can both enable and disable connections? So that there
>>>>>> could be a default connection between A and B, but there is also some
>>>>>> sort of explicit override that disables it. This would be more flexible
>>>>>> than a more global on/off switch.
>>>>>
>>>>> I'm not sure what you mean. Do you perhaps mean that the default
>>>>> connection on/off switch should be per-node (which it already is in my
>>>>> proposal), or that it should be per-connection (so that if there are
>>>>> multiple default from node A, it's possible to disable only a subset of
>>>>> those)?
>>>>>
>>>>> I didn't make make it possible to disable individual default
>>>>> connections, because I had a feeling that it would have very messy
>>>>> semantics. If default connection from A to B is disabled, what is the
>>>>> routing code supposed to do when conditions change and the default
>>>>> routing is re-evaluated? Can it ever reactivate the connection between A
>>>>> and B again? Is the per-connection disabling handled as a blacklist of
>>>>> connections that must never be automatically activated?
>>>>
>>>> If the A -> B route is explicitly_disabled, that overrides any default 
>>>> connections the routing system tries to make.
>>>
>>> What is the use case for explicitly disabled connections? I'll assume
>>> here that your idea was to allow moving a default connection elsewhere
>>> (making the connection explicit in the process) without disabling all
>>> default connections for the node.
>>>
>>> When the user moves a default connection, the routing system obviously
>>> shouldn't immediately create another default connection elsewhere to
>>> replace the disabled connection.
>>>
>>> On the other hand, if the routing system doesn't create replacement
>>> connections, then that results in weird behaviour. Let's say that
>>> there's a default connection A -> B, and the user moves the connection
>>> to A -> C. Then B disappears. The routing changes its opinion of the
>>> best available routing for A, which might be D. So removing node B
>>> resulted in audio suddenly appearing in node D, even though nothing was
>>> playing to B.
>>>
>>
>> Assume your example of a default connection A -> B which the user
>> changes into A -> C, by adding an explicit A -> C connection. Without
>> some sort of explicitly_disabled blacklist that would then include A ->
>> B, the routing system would be free to route A to *both* B and C.
> 
> My solution is that the application disables the default routing
> altogether for A, if it doesn't want to have the default connection A ->
> B. It seems to me that this causes fewer surprises than the blacklisting
> approach.
> 
>> Whether this is implemented as a bool flag or as a separate blacklist is
>> an implementation detail, but a bool flag just seemed simpler and faster
>> to me, than having to look in several lists to figure out whether a
>> connection exists or not.
> 
> You don't need to look in several lists to figure out whether a
> connection exists or not. If we have connection objects, which I think
> we both want to have, it's enough to get the list all connections and
> see whether a particular connection is included in that list.
> 

Okay, so let me see if I understand this right. You propose that you can
add explicit connections between two specified nodes, but blacklisting
default connections have to be done on a node wide level (rather than
per connection).

That sounds interesting, as it would be more resilient towards nodes
appearing and disappearing later on.
I think that blacklisting would have to be two booleans per node though,
one for outgoing connections and one for incoming. And a connection
cannot exist if it is blocked on *either* side, rather than both sides.
Does that make sense?


-- 
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic


More information about the pulseaudio-discuss mailing list