noiseorchestra / jacktrip_pypatcher

Python scripts to autopatch a JackTrip hubserver
GNU General Public License v3.0
6 stars 1 forks source link

Reduce the amount of silence when repatching #29

Open madwort opened 3 years ago

madwort commented 3 years ago

When a new client joins, there is a brief moment of silence while the patcher runs. Maybe we're doing

and maybe we could do this (with shorter silence):

ref. https://github.com/noiseorchestra/jacktrip_pypatcher/pull/25#discussion_r499161929

sandreae commented 3 years ago

What about if instead of immediately disconnecting and re-making connections, we build up an object which maps all the connections which need to be made, start relevant ladspa, then make just those new connections?

Then it would be:

sandreae commented 3 years ago

Something like this:

def connect_all(jcp, jacktrip_clients, ladspa_ports):
    """Connect all JackTrip clients to a list of ladspa ports"""
    for i, ladspa_port in enumerate(ladspa_ports):
        # don't actually connect the ports yet
        # jcp.connect_to_ladspa(jacktrip_clients[i], ladspa_port)
        jcp.connections.append([jacktrip_clients[i], ladspa_port])
        for jacktrip_client in jacktrip_clients:
            if jacktrip_client == jacktrip_clients[i]:
                continue
            else:
                # don't actually connect the ports yet
                # jcp.connect_from_ladspa(ladspa_port, jacktrip_client)
                jcp.connections.append([ladspa_port, jacktrip_client])
sandreae commented 3 years ago

This would also require some way of knowing what kind of connections we are trying to make (ladspa -> client, client -> ladspa etc..)

sandreae commented 3 years ago

This from JACK-Client would be useful for checking against existing connections:

client.get_all_connections('system:playback_1')

sandreae commented 3 years ago

Actually, of course that won't work, as clients don't necessarily have the same position when repatching. Still, this might be a good approach:

madwort commented 3 years ago

What about if instead of immediately disconnecting and re-making connections, we build up an object which maps all the connections which need to be made

Yeah, definitely, have had this as a vague long-term goal for ages - would be nice as we could then write unit tests against the thing that creates the connection maps. But, could be a lot of work to refactor this way?

madwort commented 3 years ago

Actually, of course that won't work, as clients don't necessarily have the same position when repatching

Ah, yeah, that's a good point - with the current patching strategy, maybe most people are going to get repatched most times that it runs - so there's no point in doing anything more sophisticated than disconnect everyone & reconnect everyone.

I think I was originally thinking the patcher would be constantly running (like every 10sec) so not repatching would be important, but now we have a (seemingly reliable) trigger mechanism to repatch on client connection we don't need that.

sandreae commented 3 years ago

What about if instead of immediately disconnecting and re-making connections, we build up an object which maps all the connections which need to be made

Yeah, definitely, have had this as a vague long-term goal for ages - would be nice as we could then write unit tests against the thing that creates the connection maps. But, could be a lot of work to refactor this way?

I don't know if it would be too much work to implement. Almost all connections are made in jcp.connect_ports, we could configure it to build a list at jcp.connections when in "pre_patch" mode say, then run this list through connect_all in "live" mode when we're ready.

sandreae commented 3 years ago

Actually, of course that won't work, as clients don't necessarily have the same position when repatching

Ah, yeah, that's a good point - with the current patching strategy, maybe most people are going to get repatched most times that it runs - so there's no point in doing anything more sophisticated than disconnect everyone & reconnect everyone.

I think I was originally thinking the patcher would be constantly running (like every 10sec) so not repatching would be important, but now we have a (seemingly reliable) trigger mechanism to repatch on client connection we don't need that.

Yeh, it may well not be worth it, but if we thought it was important (maybe we find the silences annoying when in sessions) then as we can now reconfigure our panning positions easily we could have a go at trying to keep clients in the same place. Guess this is one for the later pile though...

sandreae commented 3 years ago

Just experimented with doing this:

    if len(jacktrip_clients) >= 2 and len(jacktrip_clients) <= 11:
        print("=== Start LADSPA plugins ===")
        ladspa_ports = ladspa.get_ports(len(jacktrip_clients), all_ladspa_ports)
        darkice_ladspa_ports = ladspa_ports

        if len(jacktrip_clients) == 3:
            darkice_ladspa_ports = [ladspa_ports[0]] + ladspa_ports[3:]

        jcp.set_all_connections(jacktrip_clients, ladspa_ports)
        jcp.set_darkice_connections(darkice_ladspa_ports, darkice_port)
        print("=== Patch", len(jacktrip_clients), "client ===")

    # disconnect right at the end after mapping connections and starting ladspa plugins
    print("=== Disconnecting existing connections ===")
    disconnect(jackClient, dry_run, lounge_music.port)

    # then actually make the new connections
    jcp.make_all_connections()

and it works really well. The silence between re-patching is basically gone, you can still hear a bit a a click when the patching happens, but that's all. Can't implement this until the code for one client is refactored, but good to know it works.