This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

configs.gg23.audio: switch phones left on the off profile to A2DP

+29 -3
+29 -3
configs/gg23/audio/matrix.py
··· 1 1 # Audio routing matrix: one Home Assistant switch (MQTT discovery) per 2 2 # source and speaker. While a switch is on, the source's PipeWire node is 3 3 # linked to the speaker's node. Sources are the fixed nodes from the config 4 - # plus every connected Bluetooth A2DP source (bluez_input.*). A new source 5 - # starts on the config's `rooms` of it, else on all speakers. Each speaker 4 + # plus every connected Bluetooth A2DP source (bluez_input.*; phones left on 5 + # the "off" profile are switched to A2DP). A new source starts on the 6 + # config's `rooms` of it, else on all speakers. Each speaker 6 7 # also gets a volume (MQTT number), applied to its node with wpctl. Usage: 7 8 # audio-matrix CONFIG.json [--dry-run], --dry-run prints the pw-link and 8 9 # wpctl calls without running them. ··· 22 23 23 24 events = queue.Queue() 24 25 25 - # PipeWire objects by id: nodes, ports and links 26 + # PipeWire objects by id: devices, nodes, ports and links 26 27 graph = {} 27 28 interesting = { 29 + "PipeWire:Interface:Device", 28 30 "PipeWire:Interface:Node", 29 31 "PipeWire:Interface:Port", 30 32 "PipeWire:Interface:Link", ··· 92 94 ) 93 95 src["nodes"].append(i) 94 96 return found 97 + 98 + 99 + # bluez devices whose profile was switched on, so a phone that turns it off 100 + # again is left alone 101 + profiled = set() 102 + 103 + 104 + # WirePlumber leaves a newly paired phone on the "off" profile when its A2DP 105 + # transport is not up yet at connect time, so it gets no bluez_input node. 106 + # Switch such devices to the A2DP (audio-gateway) profile once. 107 + def bluetooth_profiles(): 108 + for i, info in objects("Device"): 109 + if info["props"].get("device.api") != "bluez5" or i in profiled: 110 + continue 111 + params = info.get("params", {}) 112 + current = (params.get("Profile") or [{}])[0].get("name") 113 + gateway = [ 114 + p for p in params.get("EnumProfile", []) 115 + if p.get("name") == "audio-gateway" and p.get("available") != "no" 116 + ] 117 + if current == "off" and gateway: 118 + run("wpctl", "set-profile", i, gateway[0]["index"]) 119 + profiled.add(i) 95 120 96 121 97 122 # whether both nodes have their ports to link yet ··· 239 264 240 265 241 266 def sync(): 267 + bluetooth_profiles() 242 268 found = sources() 243 269 for key in [k for k in published if k not in found]: 244 270 unpublish(key)