From 8dcf3ce6edda35949cfadfb9d6a287944848dc69 Mon Sep 17 00:00:00 2001 From: Julian Bouzas Date: Wed, 18 Mar 2026 12:32:42 -0400 Subject: [PATCH] autoswitch-bluetooth-profile: Check profile names to see if a profile is headset We cannot only rely on the input routes to check whether a profile is a headset profile or not because some BT devices can have A2DP source nodes, causing the autoswitch logic to not work properly. This patch fixes the problem by also checking if the profile name matches the 'headset-head-unit*' or 'bap-duplex' patterns. If the profile name does not match those patterns, the profile is not considered headset profile. See #926 --- .../device/autoswitch-bluetooth-profile.lua | 97 ++++++++++--------- 1 file changed, 52 insertions(+), 45 deletions(-) diff --git a/src/scripts/device/autoswitch-bluetooth-profile.lua b/src/scripts/device/autoswitch-bluetooth-profile.lua index 35e2a0fd..6ae6321c 100644 --- a/src/scripts/device/autoswitch-bluetooth-profile.lua +++ b/src/scripts/device/autoswitch-bluetooth-profile.lua @@ -86,42 +86,6 @@ function getCurrentProfile (device) return nil end -function highestPrioProfileWithInputRoute (device) - local found_profile = nil - for p in device:iterate_params ("EnumRoute") do - local route = cutils.parseParam (p, "EnumRoute") - if route ~= nil and route.profiles ~= nil and route.direction == "Input" then - for _, v in pairs (route.profiles) do - local p = findProfile (device, v) - if p ~= nil then - if found_profile == nil or found_profile.priority < p.priority then - found_profile = p - end - end - end - end - end - return found_profile -end - -function highestPrioProfileWithoutInputRoute (device) - local found_profile = nil - for p in device:iterate_params ("EnumRoute") do - local route = cutils.parseParam (p, "EnumRoute") - if route ~= nil and route.profiles ~= nil and route.direction ~= "Input" then - for _, v in pairs (route.profiles) do - local p = findProfile (device, v) - if p ~= nil then - if found_profile == nil or found_profile.priority < p.priority then - found_profile = p - end - end - end - end - end - return found_profile -end - function hasProfileInputRoute (device, profile_index) for p in device:iterate_params ("EnumRoute") do local route = cutils.parseParam (p, "EnumRoute") @@ -136,6 +100,51 @@ function hasProfileInputRoute (device, profile_index) return false end +function isHeadsetProfile (device, profile) + if hasProfileInputRoute (device, profile.index) and + (string.find (profile.name, "^headset%-head%-unit") or profile.name == "bap-duplex") then + return true + else + return false + end +end + +function highestPrioHeadsetProfile (device) + local found_profile = nil + for p in device:iterate_params ("EnumRoute") do + local route = cutils.parseParam (p, "EnumRoute") + if route ~= nil and route.profiles ~= nil and route.direction == "Input" then + for _, v in pairs (route.profiles) do + local p = findProfile (device, v) + if p ~= nil and isHeadsetProfile (device, p) then + if found_profile == nil or found_profile.priority < p.priority then + found_profile = p + end + end + end + end + end + return found_profile +end + +function highestPrioNonHeadsetProfile (device) + local found_profile = nil + for p in device:iterate_params ("EnumRoute") do + local route = cutils.parseParam (p, "EnumRoute") + if route ~= nil and route.profiles ~= nil and route.direction ~= "Input" then + for _, v in pairs (route.profiles) do + local p = findProfile (device, v) + if p ~= nil and not isHeadsetProfile (device, p) then + if found_profile == nil or found_profile.priority < p.priority then + found_profile = p + end + end + end + end + end + return found_profile +end + function switchDeviceToHeadsetProfile (dev_id, device_om) -- Find the actual device local device = device_om:lookup { @@ -148,8 +157,7 @@ function switchDeviceToHeadsetProfile (dev_id, device_om) -- Do not switch if the current profile is already a headset profile local cur_profile = getCurrentProfile (device) - if cur_profile ~= nil and - hasProfileInputRoute (device, cur_profile.index) then + if cur_profile ~= nil and isHeadsetProfile (device, cur_profile) then log:info (device, "Current profile is already a headset profile, no need to switch") return @@ -163,12 +171,12 @@ function switchDeviceToHeadsetProfile (dev_id, device_om) local profile_name = getSavedHeadsetProfile (device) if profile_name ~= nil then profile = findProfile (device, nil, profile_name) - if profile ~= nil and not hasProfileInputRoute (device, profile.index) then + if profile ~= nil and not isHeadsetProfile (device, profile) then saveHeadsetProfile (device, nil, false) end end if profile == nil then - profile = highestPrioProfileWithInputRoute (device) + profile = highestPrioHeadsetProfile (device) end -- Switch if headset profile was found @@ -198,8 +206,7 @@ function restoreProfile (dev_id, device_om) -- Do not restore if the current profile is already a non-headset profile local cur_profile = getCurrentProfile (device) - if cur_profile ~= nil and - not hasProfileInputRoute (device, cur_profile.index) then + if cur_profile ~= nil and not isHeadsetProfile (device, cur_profile) then log:info (device, "Current profile is already a non-headset profile, no need to restore") return @@ -213,12 +220,12 @@ function restoreProfile (dev_id, device_om) local profile_name = getSavedNonHeadsetProfile (device) if profile_name ~= nil then profile = findProfile (device, nil, profile_name) - if profile ~= nil and hasProfileInputRoute (device, profile.index) then + if profile ~= nil and isHeadsetProfile (device, profile) then saveNonHeadsetProfile (device, nil) end end if profile == nil then - profile = highestPrioProfileWithoutInputRoute (device) + profile = highestPrioNonHeadsetProfile (device) end -- Restore if non-headset profile was found @@ -483,7 +490,7 @@ local device_profile_changed_hook = SimpleEventHook { -- Always save the current profile when it changes local cur_profile = getCurrentProfile (device) if cur_profile ~= nil then - if hasProfileInputRoute (device, cur_profile.index) then + if isHeadsetProfile (device, cur_profile) then log:info (device, "Saving headset profile " .. cur_profile.name) saveHeadsetProfile (device, cur_profile.name, cur_profile.save) else