Server IP : 192.168.23.10 / Your IP : 3.147.195.139 Web Server : Apache System : Linux echo.premieradvertising.com 5.14.0-362.8.1.el9_3.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Nov 7 14:54:22 EST 2023 x86_64 User : rrrallyteam ( 1049) PHP Version : 8.1.31 Disable Function : exec,passthru,shell_exec,system MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF Directory (0755) : /usr/share/gettext/../gnupg/../wireplumber/scripts/monitors/ |
[ Home ] | [ C0mmand ] | [ Upload File ] |
---|
-- WirePlumber -- -- Copyright © 2021 Collabora Ltd. -- @author George Kiagiadakis <george.kiagiadakis@collabora.com> -- -- SPDX-License-Identifier: MIT local config = ... or {} devices_om = ObjectManager { Interest { type = "device", } } nodes_om = ObjectManager { Interest { type = "node", Constraint { "node.name", "#", "*.bluez_*put*"}, Constraint { "device.id", "+" }, } } -- preprocess rules and create Interest objects for _, r in ipairs(config.rules or {}) do r.interests = {} for _, i in ipairs(r.matches) do local interest_desc = { type = "properties" } for _, c in ipairs(i) do c.type = "pw" table.insert(interest_desc, Constraint(c)) end local interest = Interest(interest_desc) table.insert(r.interests, interest) end r.matches = nil end -- applies properties from config.rules when asked to function rulesApplyProperties(properties) for _, r in ipairs(config.rules or {}) do if r.apply_properties then for _, interest in ipairs(r.interests) do if interest:matches(properties) then for k, v in pairs(r.apply_properties) do properties[k] = v end end end end end end function setOffloadActive(device, value) local pod = Pod.Object { "Spa:Pod:Object:Param:Props", "Props", bluetoothOffloadActive = value } device:set_params("Props", pod) end nodes_om:connect("object-added", function(_, node) node:connect("state-changed", function(node, old_state, cur_state) local interest = Interest { type = "device", Constraint { "object.id", "=", node.properties["device.id"]} } for d in devices_om:iterate (interest) do if cur_state == "running" then setOffloadActive(d, true) else setOffloadActive(d, false) end end end) end) function createOffloadScoNode(parent, id, type, factory, properties) local dev_props = parent.properties local args = { ["audio.channels"] = 1, ["audio.position"] = "[MONO]", } local desc = dev_props["device.description"] or dev_props["device.name"] or dev_props["device.nick"] or dev_props["device.alias"] or "bluetooth-device" -- sanitize description, replace ':' with ' ' args["node.description"] = desc:gsub("(:)", " ") if factory:find("sink") then local capture_args = { ["device.id"] = parent["bound-id"], ["media.class"] = "Audio/Sink", ["node.pause-on-idle"] = false, } for k, v in pairs(properties) do capture_args[k] = v end local name = "bluez_output" .. "." .. (properties["api.bluez5.address"] or dev_props["device.name"]) .. "." .. tostring(id) args["node.name"] = name:gsub("([^%w_%-%.])", "_") args["capture.props"] = Json.Object(capture_args) args["playback.props"] = Json.Object { ["node.passive"] = true, ["node.pause-on-idle"] = false, } elseif factory:find("source") then local playback_args = { ["device.id"] = parent["bound-id"], ["media.class"] = "Audio/Source", ["node.pause-on-idle"] = false, } for k, v in pairs(properties) do playback_args[k] = v end local name = "bluez_input" .. "." .. (properties["api.bluez5.address"] or dev_props["device.name"]) .. "." .. tostring(id) args["node.name"] = name:gsub("([^%w_%-%.])", "_") args["capture.props"] = Json.Object { ["node.passive"] = true, ["node.pause-on-idle"] = false, } args["playback.props"] = Json.Object(playback_args) else Log.warning(parent, "Unsupported factory: " .. factory) return end -- Transform 'args' to a json object here local args_json = Json.Object(args) -- and get the final JSON as a string from the json object local args_string = args_json:get_data() local loopback_properties = {} local loopback = LocalModule("libpipewire-module-loopback", args_string, loopback_properties) parent:store_managed_object(id, loopback) end function createNode(parent, id, type, factory, properties) local dev_props = parent.properties if config.properties["bluez5.hw-offload-sco"] and factory:find("sco") then createOffloadScoNode(parent, id, type, factory, properties) return end -- set the device id and spa factory name; REQUIRED, do not change properties["device.id"] = parent["bound-id"] properties["factory.name"] = factory -- set the default pause-on-idle setting properties["node.pause-on-idle"] = false -- set the node description local desc = dev_props["device.description"] or dev_props["device.name"] or dev_props["device.nick"] or dev_props["device.alias"] or "bluetooth-device" -- sanitize description, replace ':' with ' ' properties["node.description"] = desc:gsub("(:)", " ") -- set the node name local name = ((factory:find("sink") and "bluez_output") or (factory:find("source") and "bluez_input" or factory)) .. "." .. (properties["api.bluez5.address"] or dev_props["device.name"]) .. "." .. tostring(id) -- sanitize name properties["node.name"] = name:gsub("([^%w_%-%.])", "_") -- set priority if not properties["priority.driver"] then local priority = factory:find("source") and 2010 or 1010 properties["priority.driver"] = priority properties["priority.session"] = priority end -- autoconnect if it's a stream if properties["api.bluez5.profile"] == "headset-audio-gateway" or properties["api.bluez5.profile"] == "bap-sink" or factory:find("a2dp.source") or factory:find("media.source") then properties["node.autoconnect"] = true end -- apply properties from config.rules rulesApplyProperties(properties) -- create the node; bluez requires "local" nodes, i.e. ones that run in -- the same process as the spa device, for several reasons local node = LocalNode("adapter", properties) node:activate(Feature.Proxy.BOUND) parent:store_managed_object(id, node) end function createDevice(parent, id, type, factory, properties) local device = parent:get_managed_object(id) if not device then -- ensure a proper device name local name = (properties["device.name"] or properties["api.bluez5.address"] or properties["device.description"] or tostring(id)):gsub("([^%w_%-%.])", "_") if not name:find("^bluez_card%.", 1) then name = "bluez_card." .. name end properties["device.name"] = name -- set the icon name if not properties["device.icon-name"] then local icon = nil local icon_map = { -- form factor -> icon ["microphone"] = "audio-input-microphone", ["webcam"] = "camera-web", ["handset"] = "phone", ["portable"] = "multimedia-player", ["tv"] = "video-display", ["headset"] = "audio-headset", ["headphone"] = "audio-headphones", ["speaker"] = "audio-speakers", ["hands-free"] = "audio-handsfree", } local f = properties["device.form-factor"] local b = properties["device.bus"] icon = icon_map[f] or "audio-card" properties["device.icon-name"] = icon .. (b and ("-" .. b) or "") end -- initial profile is to be set by policy-device-profile.lua, not spa-bluez5 properties["bluez5.profile"] = "off" -- apply properties from config.rules rulesApplyProperties(properties) -- create the device device = SpaDevice(factory, properties) if device then device:connect("create-object", createNode) parent:store_managed_object(id, device) else Log.warning ("Failed to create '" .. factory .. "' device") return end end Log.info(parent, string.format("%d, %s (%s): %s", id, properties["device.description"], properties["api.bluez5.address"], properties["api.bluez5.connection"])) -- activate the device after the bluez profiles are connected if properties["api.bluez5.connection"] == "connected" then device:activate(Feature.SpaDevice.ENABLED | Feature.Proxy.BOUND) else device:deactivate(Features.ALL) end end function createMonitor() local monitor_props = config.properties or {} monitor_props["api.bluez5.connection-info"] = true local monitor = SpaDevice("api.bluez5.enum.dbus", monitor_props) if monitor then monitor:connect("create-object", createDevice) else Log.message("PipeWire's BlueZ SPA missing or broken. Bluetooth not supported.") return nil end monitor:activate(Feature.SpaDevice.ENABLED) return monitor end logind_plugin = Plugin.find("logind") if logind_plugin then -- if logind support is enabled, activate -- the monitor only when the seat is active function startStopMonitor(seat_state) Log.info(logind_plugin, "Seat state changed: " .. seat_state) if seat_state == "active" then monitor = createMonitor() elseif monitor then monitor:deactivate(Feature.SpaDevice.ENABLED) monitor = nil end end logind_plugin:connect("state-changed", function(p, s) startStopMonitor(s) end) startStopMonitor(logind_plugin:call("get-state")) else monitor = createMonitor() end nodes_om:activate() devices_om:activate()