2022-01-26 16:46:52 -05:00
|
|
|
-- WirePlumber
|
|
|
|
|
--
|
|
|
|
|
-- Copyright © 2022 Collabora Ltd.
|
|
|
|
|
-- @author Julian Bouzas <julian.bouzas@collabora.com>
|
|
|
|
|
--
|
|
|
|
|
-- SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
|
|
local self = {}
|
|
|
|
|
self.active_profiles = {}
|
2022-07-12 08:42:55 +05:30
|
|
|
self.default_profile_plugin = Plugin.find ("default-profile")
|
2022-01-26 16:46:52 -05:00
|
|
|
|
2022-02-14 11:29:03 -05:00
|
|
|
-- Checks whether a device profile is persistent or not
|
2022-07-12 08:42:55 +05:30
|
|
|
function isProfilePersistent (device_props, profile_name)
|
2022-05-09 12:48:10 +05:30
|
|
|
local matched, mprops = Settings.apply_rule ("device", device_props)
|
|
|
|
|
|
|
|
|
|
if (matched and mprops) then
|
2022-07-12 08:42:55 +05:30
|
|
|
if string.find (mprops ["profile_names"], profile_name) then
|
2022-05-09 12:48:10 +05:30
|
|
|
return true
|
2022-02-14 11:29:03 -05:00
|
|
|
end
|
|
|
|
|
end
|
2022-05-09 12:48:10 +05:30
|
|
|
|
2022-02-14 11:29:03 -05:00
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
2022-07-12 08:42:55 +05:30
|
|
|
function parseParam (param, id)
|
|
|
|
|
local parsed = param:parse ()
|
2022-01-26 16:46:52 -05:00
|
|
|
if parsed.pod_type == "Object" and parsed.object_id == id then
|
|
|
|
|
return parsed.properties
|
|
|
|
|
else
|
|
|
|
|
return nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function setDeviceProfile (device, dev_id, dev_name, profile)
|
2022-07-12 08:42:55 +05:30
|
|
|
if self.active_profiles [dev_id] and
|
|
|
|
|
self.active_profiles [dev_id].index == profile.index then
|
2022-01-26 16:46:52 -05:00
|
|
|
Log.info ("Profile " .. profile.name .. " is already set in " .. dev_name)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local param = Pod.Object {
|
|
|
|
|
"Spa:Pod:Object:Param:Profile", "Profile",
|
|
|
|
|
index = profile.index,
|
|
|
|
|
}
|
|
|
|
|
Log.info ("Setting profile " .. profile.name .. " on " .. dev_name)
|
2022-07-12 08:42:55 +05:30
|
|
|
device:set_param ("Profile", param)
|
2022-01-26 16:46:52 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function findDefaultProfile (device)
|
|
|
|
|
local def_name = nil
|
|
|
|
|
|
|
|
|
|
if self.default_profile_plugin ~= nil then
|
|
|
|
|
def_name = self.default_profile_plugin:call ("get-profile", device)
|
|
|
|
|
end
|
|
|
|
|
if def_name == nil then
|
|
|
|
|
return nil
|
|
|
|
|
end
|
|
|
|
|
|
2022-07-12 08:42:55 +05:30
|
|
|
for p in device:iterate_params ("EnumProfile") do
|
|
|
|
|
local profile = parseParam (p, "EnumProfile")
|
2022-01-26 16:46:52 -05:00
|
|
|
if profile.name == def_name then
|
|
|
|
|
return profile
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function findBestProfile (device)
|
|
|
|
|
local off_profile = nil
|
|
|
|
|
local best_profile = nil
|
|
|
|
|
local unk_profile = nil
|
|
|
|
|
|
2022-07-12 08:42:55 +05:30
|
|
|
for p in device:iterate_params ("EnumProfile") do
|
|
|
|
|
profile = parseParam (p, "EnumProfile")
|
2022-01-26 16:46:52 -05:00
|
|
|
if profile and profile.name ~= "pro-audio" then
|
|
|
|
|
if profile.name == "off" then
|
|
|
|
|
off_profile = profile
|
|
|
|
|
elseif profile.available == "yes" then
|
|
|
|
|
if best_profile == nil or profile.priority > best_profile.priority then
|
|
|
|
|
best_profile = profile
|
|
|
|
|
end
|
|
|
|
|
elseif profile.available ~= "no" then
|
|
|
|
|
if unk_profile == nil or profile.priority > unk_profile.priority then
|
|
|
|
|
unk_profile = profile
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if best_profile ~= nil then
|
|
|
|
|
return best_profile
|
|
|
|
|
elseif unk_profile ~= nil then
|
|
|
|
|
return unk_profile
|
|
|
|
|
elseif off_profile ~= nil then
|
|
|
|
|
return off_profile
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
end
|
|
|
|
|
|
2022-02-14 11:29:03 -05:00
|
|
|
function handleProfiles (device, new_device)
|
2022-07-12 08:42:55 +05:30
|
|
|
local dev_id = device ["bound-id"]
|
|
|
|
|
local dev_name = device.properties ["device.name"]
|
2022-01-26 16:46:52 -05:00
|
|
|
|
2022-02-19 09:11:57 -05:00
|
|
|
local def_profile = findDefaultProfile (device)
|
|
|
|
|
|
|
|
|
|
-- Do not do anything if active profile is both persistent and default
|
|
|
|
|
if not new_device and
|
2022-07-12 08:42:55 +05:30
|
|
|
self.active_profiles [dev_id] ~= nil and
|
|
|
|
|
isProfilePersistent (device.properties,
|
|
|
|
|
self.active_profiles [dev_id].name) and
|
2022-02-19 09:11:57 -05:00
|
|
|
def_profile ~= nil and
|
2022-07-12 08:42:55 +05:30
|
|
|
self.active_profiles [dev_id].name == def_profile.name
|
2022-02-19 09:11:57 -05:00
|
|
|
then
|
2022-07-12 08:42:55 +05:30
|
|
|
local active_profile = self.active_profiles [dev_id].name
|
|
|
|
|
Log.info ("Device profile " .. active_profile .. " is persistent for "
|
|
|
|
|
.. dev_name)
|
2022-02-14 11:29:03 -05:00
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
2022-04-25 10:28:24 +03:00
|
|
|
if def_profile ~= nil then
|
|
|
|
|
if def_profile.available == "no" then
|
|
|
|
|
Log.info ("Default profile " .. def_profile.name .. " unavailable for " .. dev_name)
|
2022-01-26 16:46:52 -05:00
|
|
|
else
|
2022-04-25 10:28:24 +03:00
|
|
|
Log.info ("Found default profile " .. def_profile.name .. " for " .. dev_name)
|
|
|
|
|
setDeviceProfile (device, dev_id, dev_name, def_profile)
|
|
|
|
|
return
|
2022-01-26 16:46:52 -05:00
|
|
|
end
|
2022-04-25 10:28:24 +03:00
|
|
|
else
|
|
|
|
|
Log.info ("Default profile not found for " .. dev_name)
|
2022-01-26 16:46:52 -05:00
|
|
|
end
|
|
|
|
|
|
2022-07-31 10:09:32 -04:00
|
|
|
local best_profile = findBestProfile (device)
|
|
|
|
|
if best_profile ~= nil then
|
|
|
|
|
Log.info ("Found best profile " .. best_profile.name .. " for " .. dev_name)
|
2022-01-26 16:46:52 -05:00
|
|
|
setDeviceProfile (device, dev_id, dev_name, best_profile)
|
|
|
|
|
else
|
|
|
|
|
Log.info ("Best profile not found on " .. dev_name)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function onDeviceParamsChanged (device, param_name)
|
|
|
|
|
if param_name == "EnumProfile" then
|
2022-02-14 11:29:03 -05:00
|
|
|
handleProfiles (device, false)
|
2022-01-26 16:46:52 -05:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
self.om = ObjectManager {
|
|
|
|
|
Interest {
|
|
|
|
|
type = "device",
|
|
|
|
|
Constraint { "device.name", "is-present", type = "pw-global" },
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-12 08:42:55 +05:30
|
|
|
self.om:connect ("object-added", function (_, device)
|
2022-01-26 16:46:52 -05:00
|
|
|
device:connect ("params-changed", onDeviceParamsChanged)
|
2022-02-14 11:29:03 -05:00
|
|
|
handleProfiles (device, true)
|
2022-01-26 16:46:52 -05:00
|
|
|
end)
|
|
|
|
|
|
2022-07-12 08:42:55 +05:30
|
|
|
self.om:connect ("object-removed", function (_, device)
|
|
|
|
|
local dev_id = device ["bound-id"]
|
|
|
|
|
self.active_profiles [dev_id] = nil
|
2022-03-28 20:16:52 +03:00
|
|
|
end)
|
|
|
|
|
|
2022-07-12 08:42:55 +05:30
|
|
|
self.om:activate ()
|