mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-09 07:28:41 +02:00
scripts: delete policy-node.lua
This has been split into smaller files in policy-desktop/
This commit is contained in:
parent
993a2686f6
commit
5c113d2745
1 changed files with 0 additions and 402 deletions
|
|
@ -1,402 +0,0 @@
|
|||
-- WirePlumber
|
||||
--
|
||||
-- Copyright © 2020 Collabora Ltd.
|
||||
-- @author Julian Bouzas <julian.bouzas@collabora.com>
|
||||
--
|
||||
-- SPDX-License-Identifier: MIT
|
||||
|
||||
-- policy-node.lua is the main policy script, it watches for any changes that
|
||||
-- can affect the routing(stream to device links) and takes necessary actions.
|
||||
-- For example: It watches for stream nodes to show up and links them to
|
||||
-- appropriate target device. It watches for new device preferece of the
|
||||
-- user(via pavuctrl or gnome settins or metadata etc) and moves the existing
|
||||
-- sessions to that device(if the device is valid). It watches for new devices
|
||||
-- to show up(usb headset is plugged in or if BT is paired) and moves the
|
||||
-- existing streams to that device.
|
||||
|
||||
-- settings file: policy.conf
|
||||
|
||||
|
||||
local putils = require ("policy-utils")
|
||||
local cutils = require ("common-utils")
|
||||
local config = require ("policy-config")
|
||||
|
||||
find_target_events = {}
|
||||
|
||||
function parseBool (var)
|
||||
return cutils.parseBool (var)
|
||||
end
|
||||
|
||||
function unhandleLinkable (si)
|
||||
local si_id = si.id
|
||||
local si_flags = putils.get_flags (si_id)
|
||||
local valid, si_props = checkLinkable (si, true)
|
||||
if not valid then
|
||||
return
|
||||
end
|
||||
|
||||
Log.info (si, string.format ("unhandling item: %s (%s)",
|
||||
tostring (si_flags.node_name), tostring (si_flags.node_id)))
|
||||
|
||||
-- remove any links associated with this item
|
||||
for silink in links_om:iterate () do
|
||||
local out_id = tonumber (silink.properties ["out.item.id"])
|
||||
local in_id = tonumber (silink.properties ["in.item.id"])
|
||||
if out_id == si.id or in_id == si.id then
|
||||
if out_id == si.id and
|
||||
si_flags and si_flags.peer_id == out_id then
|
||||
si_flags.peer_id = nil
|
||||
elseif in_id == si.id and
|
||||
si_flags and si_flags.peer_id == in_id then
|
||||
si_flags.peer_id = nil
|
||||
end
|
||||
silink:remove ()
|
||||
Log.info (silink, "... link removed")
|
||||
end
|
||||
end
|
||||
|
||||
si_flags = nil
|
||||
putils.set_flags (si_id, si_flags)
|
||||
end
|
||||
|
||||
function handleLinkable (si)
|
||||
local si_id = si.id;
|
||||
|
||||
local valid, si_props = checkLinkable (si)
|
||||
if not valid then
|
||||
return
|
||||
end
|
||||
|
||||
-- check if we need to link this node at all
|
||||
local autoconnect = parseBool (si_props ["node.autoconnect"])
|
||||
if not autoconnect then
|
||||
Log.debug (si, tostring (si_props ["node.name"]) .. " does not need to be autoconnected")
|
||||
return
|
||||
end
|
||||
|
||||
if not find_target_events [si_id] then
|
||||
find_target_events [si_id] = nil
|
||||
end
|
||||
|
||||
if find_target_events [si_id] ~= nil then
|
||||
-- stop the processing of the old event, we are going to queue a new one any
|
||||
-- way
|
||||
Log.info(si, string.format("stopping item: %s (%s) si id(%s)",
|
||||
tostring(si_props["node.name"]), tostring(si_props["node.id"]), si_id))
|
||||
|
||||
find_target_events [si_id]:stop_processing ()
|
||||
end
|
||||
|
||||
find_target_events [si_id] = EventDispatcher.push_event {
|
||||
type = "find-target-si-and-link", priority = 10, subject = si
|
||||
}
|
||||
end
|
||||
|
||||
function rescan ()
|
||||
Log.info ("rescanning..")
|
||||
for si in linkables_om:iterate () do
|
||||
handleLinkable (si)
|
||||
end
|
||||
end
|
||||
|
||||
function checkLinkable (si, handle_nonstreams)
|
||||
-- only handle stream session items
|
||||
local si_props = si.properties
|
||||
if not si_props or (si_props ["item.node.type"] ~= "stream"
|
||||
and not handle_nonstreams) then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Determine if we can handle item by this policy
|
||||
if endpoints_om:get_n_objects () > 0 and
|
||||
si_props ["item.factory.name"] == "si-audio-adapter" then
|
||||
return false
|
||||
end
|
||||
|
||||
return true, si_props
|
||||
end
|
||||
|
||||
function findAssociatedLinkGroupNode (si)
|
||||
local si_props = si.properties
|
||||
local node = si:get_associated_proxy ("node")
|
||||
local link_group = node.properties ["node.link-group"]
|
||||
if link_group == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- get the associated media class
|
||||
local assoc_direction = cutils.getTargetDirection (si_props)
|
||||
local assoc_media_class =
|
||||
si_props ["media.type"] ..
|
||||
(assoc_direction == "input" and "/Sink" or "/Source")
|
||||
|
||||
-- find the linkable with same link group and matching assoc media class
|
||||
for assoc_si in linkables_om:iterate () do
|
||||
local assoc_node = assoc_si:get_associated_proxy ("node")
|
||||
local assoc_link_group = assoc_node.properties ["node.link-group"]
|
||||
if assoc_link_group == link_group and
|
||||
assoc_media_class == assoc_node.properties ["media.class"] then
|
||||
return assoc_si
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function onLinkGroupPortsStateChanged (si, old_state, new_state)
|
||||
local new_str = tostring (new_state)
|
||||
local si_props = si.properties
|
||||
|
||||
-- only handle items with configured ports state
|
||||
if new_str ~= "configured" then
|
||||
return
|
||||
end
|
||||
|
||||
Log.info (si, "ports format changed on " .. si_props ["node.name"])
|
||||
|
||||
-- find associated device
|
||||
local si_device = findAssociatedLinkGroupNode (si)
|
||||
if si_device ~= nil then
|
||||
local device_node_name = si_device.properties ["node.name"]
|
||||
|
||||
-- get the stream format
|
||||
local f, m = si:get_ports_format ()
|
||||
|
||||
-- unregister the device
|
||||
Log.info (si_device, "unregistering " .. device_node_name)
|
||||
si_device:remove ()
|
||||
|
||||
-- set new format in the device
|
||||
Log.info (si_device, "setting new format in " .. device_node_name)
|
||||
si_device:set_ports_format (f, m, function (item, e)
|
||||
if e ~= nil then
|
||||
Log.warning (item, "failed to configure ports in " ..
|
||||
device_node_name .. ": " .. e)
|
||||
end
|
||||
|
||||
-- register back the device
|
||||
Log.info (item, "registering " .. device_node_name)
|
||||
item:register ()
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function checkFiltersPortsState (si)
|
||||
local si_props = si.properties
|
||||
local node = si:get_associated_proxy ("node")
|
||||
local link_group = node.properties ["node.link-group"]
|
||||
local si_id = si.id
|
||||
local si_flags = putils.get_flags (si_id)
|
||||
|
||||
-- only listen for ports state changed on audio filter streams
|
||||
if si_flags.ports_state_signal ~= true and
|
||||
si_props ["item.factory.name"] == "si-audio-adapter" and
|
||||
si_props ["item.node.type"] == "stream" and
|
||||
link_group ~= nil then
|
||||
si:connect ("adapter-ports-state-changed", onLinkGroupPortsStateChanged)
|
||||
si_flags.ports_state_signal = true
|
||||
putils.set_flags (si_id, si_flags)
|
||||
Log.info (si, "listening ports state changed on " .. si_props ["node.name"])
|
||||
end
|
||||
end
|
||||
|
||||
SimpleEventHook {
|
||||
name = "handle-linkable@policy-node",
|
||||
type = "on-event",
|
||||
priority = "linkable-added-create-item",
|
||||
interests = {
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "object-added" },
|
||||
Constraint { "event.subject.type", "=", "linkable" },
|
||||
Constraint { "item.factory.name", "c", "si-audio-adapter", "si-node" },
|
||||
Constraint { "media.class", "#", "Stream/*", type = "pw-global" },
|
||||
Constraint { "active-features", "!", 0, type = "gobject" },
|
||||
},
|
||||
},
|
||||
execute = function (event)
|
||||
local si = event:get_subject ()
|
||||
local si_props = si.properties
|
||||
|
||||
-- Forward filters ports format to associated virtual devices if enabled
|
||||
if config.filter_forward_format then
|
||||
checkFiltersPortsState (si)
|
||||
end
|
||||
|
||||
handleLinkable (si)
|
||||
end
|
||||
}:register ()
|
||||
|
||||
SimpleEventHook {
|
||||
name = "linkable-removed@policy-node",
|
||||
type = "on-event",
|
||||
priority = "linkable-removed-create-item",
|
||||
interests = {
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "object-removed" },
|
||||
Constraint { "event.subject.type", "=", "linkable" },
|
||||
},
|
||||
},
|
||||
execute = function (event)
|
||||
local si = event:get_subject ()
|
||||
unhandleLinkable (si)
|
||||
end
|
||||
}:register ()
|
||||
|
||||
SimpleEventHook {
|
||||
name = "rescan-policy",
|
||||
priority = "rescan-policy",
|
||||
type = "after-events",
|
||||
interests = {
|
||||
-- on audio device node linkable addition
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "object-added" },
|
||||
Constraint { "event.subject.type", "=", "linkable" },
|
||||
Constraint { "item.factory.name", "c", "si-audio-adapter", "si-node" },
|
||||
Constraint { "media.class", "#", "Audio/*", type = "pw-global" },
|
||||
Constraint { "active-features", "!", 0, type = "gobject" },
|
||||
},
|
||||
-- on video device node linkable addition
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "object-added" },
|
||||
Constraint { "event.subject.type", "=", "linkable" },
|
||||
Constraint { "item.factory.name", "c", "si-audio-adapter", "si-node" },
|
||||
Constraint { "media.class", "#", "Video/*", type = "pw-global" },
|
||||
Constraint { "active-features", "!", 0, type = "gobject" },
|
||||
},
|
||||
-- on audio device node linkable removal
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "object-removed" },
|
||||
Constraint { "event.subject.type", "=", "linkable" },
|
||||
Constraint { "item.factory.name", "c", "si-audio-adapter", "si-node" },
|
||||
Constraint { "media.class", "#", "Audio/*", type = "pw-global" },
|
||||
Constraint { "active-features", "!", 0, type = "gobject" },
|
||||
},
|
||||
-- on video device node linkable removal
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "object-removed" },
|
||||
Constraint { "event.subject.type", "=", "linkable" },
|
||||
Constraint { "item.factory.name", "c", "si-audio-adapter", "si-node" },
|
||||
Constraint { "media.class", "#", "Video/*", type = "pw-global" },
|
||||
Constraint { "active-features", "!", 0, type = "gobject" },
|
||||
},
|
||||
-- on device Routes changed
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "params-changed" },
|
||||
Constraint { "event.subject.type", "=", "device" },
|
||||
Constraint { "event.subject.param-id", "=", "Route" },
|
||||
},
|
||||
},
|
||||
execute = function ()
|
||||
rescan ()
|
||||
end
|
||||
}:register ()
|
||||
|
||||
local follow_hook_handle = nil
|
||||
|
||||
local function handleFollowSetting (enable)
|
||||
if (follow_hook_handle == nil) and (enable == true) then
|
||||
follow_hook_handle = SimpleEventHook {
|
||||
name = "follow@policy-node",
|
||||
type = "after-events",
|
||||
priority = "rescan-policy",
|
||||
interests = {
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "object-changed" },
|
||||
Constraint { "event.subject.type", "=", "metadata" },
|
||||
Constraint { "metadata.name", "=", "default" },
|
||||
Constraint { "event.subject.key", "=", "default.audio.source" },
|
||||
},
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "object-changed" },
|
||||
Constraint { "event.subject.type", "=", "metadata" },
|
||||
Constraint { "metadata.name", "=", "default" },
|
||||
Constraint { "event.subject.key", "=", "default.audio.sink" },
|
||||
},
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "object-changed" },
|
||||
Constraint { "event.subject.type", "=", "metadata" },
|
||||
Constraint { "metadata.name", "=", "default" },
|
||||
Constraint { "event.subject.key", "=", "default.video.source" },
|
||||
},
|
||||
},
|
||||
execute = function ()
|
||||
rescan ()
|
||||
end
|
||||
}
|
||||
follow_hook_handle:register ()
|
||||
elseif (follow_hook_handle ~= nil) and (enable == false) then
|
||||
follow_hook_handle:remove ()
|
||||
follow_hook_handle = nil
|
||||
end
|
||||
end
|
||||
|
||||
local move_hook_handle = nil
|
||||
|
||||
function handleMoveSetting (enable)
|
||||
if (move_hook_handle == nil) and (enable == true) then
|
||||
move_hook_handle = SimpleEventHook {
|
||||
name = "move@policy-node",
|
||||
type = "after-events",
|
||||
priority = "rescan-policy",
|
||||
interests = {
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "object-changed" },
|
||||
Constraint { "event.subject.type", "=", "metadata" },
|
||||
Constraint { "metadata.name", "=", "default" },
|
||||
Constraint { "event.subject.key", "=", "target.node" },
|
||||
},
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "object-changed" },
|
||||
Constraint { "event.subject.type", "=", "metadata" },
|
||||
Constraint { "metadata.name", "=", "default" },
|
||||
Constraint { "event.subject.key", "=", "target.object" },
|
||||
},
|
||||
},
|
||||
execute = function ()
|
||||
rescan ()
|
||||
end
|
||||
}
|
||||
move_hook_handle:register()
|
||||
elseif (move_hook_handle ~= nil) and (enable == false) then
|
||||
move_hook_handle:remove ()
|
||||
move_hook_handle = nil
|
||||
end
|
||||
end
|
||||
|
||||
handleMoveSetting (config.move)
|
||||
handleFollowSetting (config.follow)
|
||||
|
||||
default_nodes = Plugin.find ("default-nodes-api")
|
||||
|
||||
endpoints_om = ObjectManager { Interest { type = "SiEndpoint" } }
|
||||
|
||||
linkables_om = ObjectManager {
|
||||
Interest {
|
||||
type = "SiLinkable",
|
||||
-- only handle si-audio-adapter and si-node
|
||||
Constraint { "item.factory.name", "c", "si-audio-adapter", "si-node" },
|
||||
Constraint { "active-features", "!", 0, type = "gobject" },
|
||||
}
|
||||
}
|
||||
|
||||
pending_linkables_om = ObjectManager {
|
||||
Interest {
|
||||
type = "SiLinkable",
|
||||
-- only handle si-audio-adapter and si-node
|
||||
Constraint { "item.factory.name", "c", "si-audio-adapter", "si-node" },
|
||||
Constraint { "active-features", "=", 0, type = "gobject" },
|
||||
}
|
||||
}
|
||||
|
||||
links_om = ObjectManager {
|
||||
Interest {
|
||||
type = "SiLink",
|
||||
-- only handle links created by this policy
|
||||
Constraint { "is.policy.item.link", "=", true },
|
||||
}
|
||||
}
|
||||
|
||||
endpoints_om:activate ()
|
||||
linkables_om:activate ()
|
||||
pending_linkables_om:activate ()
|
||||
links_om:activate ()
|
||||
Loading…
Add table
Reference in a new issue