-- As explained on: https://bennett.dev/auto-link-pipewire-ports-wireplumber/ -- -- This script automatically connects the audio device specified to liquidsoap. -- Thanks to Bennett Hardwick <me@bennetthardwick.com> -- Link two ports together function link_port(output_port, input_port) if not input_port or not output_port then return false end local link_args = { ["link.input.node"] = input_port.properties["node.id"], ["link.input.port"] = input_port.properties["object.id"], ["link.output.node"] = output_port.properties["node.id"], ["link.output.port"] = output_port.properties["object.id"], -- The node never got created if it didn't have this field set to something ["object.id"] = nil, -- I was running into issues when I didn't have this set ["object.linger"] = true, ["node.description"] = "AURA Link created by auto_connect_ports" } local link = Link("link-factory", link_args) link:activate(1) return true end function delete_link(link_om, output_port, input_port) print("Trying to delete") if not input_port or not output_port then print("No ports") return false end local link = link_om:lookup { Constraint { "link.input.node", "equals", input_port.properties["node.id"] }, Constraint { "link.input.port", "equals", input_port.properties["object.id"], }, Constraint { "link.output.node", "equals", output_port.properties["node.id"], }, Constraint { "link.output.port", "equals", output_port.properties["object.id"], } } if not link then print("No link!") return end print("Deleting link!") link:request_destroy() end -- Automatically link ports together by their specific audio channels. -- -- ┌──────────────────┐ ┌───────────────────┐ -- │ │ │ │ -- │ FL ├────────►│ AUX0 │ -- │ OUTPUT │ │ │ -- │ FR ├────────►│ AUX1 INPUT │ -- │ │ │ │ -- └──────────────────┘ │ AUX2 │ -- │ │ -- └───────────────────┘ -- -- -- Call this method inside a script in global scope -- -- auto_connect_ports { -- -- -- A constraint for all the required ports of the output device -- output = Constraint { "node.name"} -- -- -- A constraint for all the required ports of the input device -- input = Constraint { .. } -- -- -- A mapping of output audio channels to input audio channels -- -- connections = { -- ["FL"] = "AUX0" -- ["FR"] = "AUX1" -- } -- -- } -- function auto_connect_ports(args) local output_om = ObjectManager { Interest { type = "port", args["output"], Constraint { "port.direction", "equals", "out" } } } local input_om = ObjectManager { Interest { type = "port", args["input"], Constraint { "port.direction", "equals", "in" } } } local all_links = ObjectManager { Interest { type = "link", } } local unless = nil if args["unless"] then unless = ObjectManager { Interest { type = "port", args["unless"], Constraint { "port.direction", "equals", "in" } } } end -- handle the connect argument function _connect() local delete_links = unless and unless:get_n_objects() > 0 for output_name, input_name in pairs(args.connect) do local output = output_om:lookup { Constraint { "port.name", "matches", string.format("*%s", output_name) }} local input = input_om:lookup { Constraint { "port.name", "matches", string.format("*%s", input_name) }} if delete_links then delete_link(all_links, output, input) else link_port(output, input) end end end output_om:connect("object-added", _connect) input_om:connect("object-added", _connect) all_links:connect("object-added", _connect) output_om:activate() input_om:activate() all_links:activate() if unless then unless:connect("object-added", _connect) unless:connect("object-removed", _connect) unless:activate() end end -- -- Fill in your port.alias and port.name -- -- Auto connect Yamaha sink to the first two channels of the Yamaha local audio_source_input = os.getenv("AURA_ENGINE_INPUT_DEVICE") local audio_input_channel_left = os.getenv("AURA_ENGINE_INPUT_CHANNEL_LEFT") local audio_input_channel_right = os.getenv("AURA_ENGINE_INPUT_CHANNEL_RIGHT") local audio_source_output = os.getenv("AURA_ENGINE_OUTPUT_DEVICE") local audio_output_channel_left = os.getenv("AURA_ENGINE_OUTPUT_CHANNEL_LEFT") local audio_output_channel_right = os.getenv("AURA_ENGINE_OUTPUT_CHANNEL_RIGHT") -- print(string.format("%s_*", audio_source_input)) auto_connect_ports { output = Constraint { "port.alias", "matches", audio_source_input .. "_*" }, input = Constraint { "port.alias", "matches", "in_line_0:*" }, connect = { [audio_input_channel_left] = "in_0", [audio_input_channel_right] = "in_1" } } auto_connect_ports { output = Constraint { "port.alias", "matches", "lineout_0:*" }, input = Constraint { "port.alias", "matches", audio_source_output .. "_*" }, connect = { ["out_0"] = audio_output_channel_left, ["out_1"] = audio_output_channel_right } }