auto "ˆl–Ãa¾”ÔD¨ µÕÆ™¸ÛªbÑ¿¿ ƒtM·ÁÄW-- WirePlumber -- -- Copyright © 2025 Collabora Ltd. -- @author Julian Bouzas -- -- SPDX-License-Identifier: MIT cutils = require ("common-utils") log = Log.open_topic ("s-automute-alsa-routes") function setRoute (device, route, mute) local param = Pod.Object { "Spa:Pod:Object:Param:Route", "Route", index = route.index, device = route.device, props = Pod.Object { "Spa:Pod:Object:Param:Props", "Route", mute = mute }, save = false, } log:info (device, "Setting mute to " .. tostring(mute) .. " on route " .. route.name) device:set_param("Route", param) end function findLowestPriorityAvailableOutputRoute (device) local lowest_prio_r = nil for p in device:iterate_params("Route") do local route = cutils.parseParam (p, "Route") if route and route.direction == "Output" and route.available ~= "no" then if lowest_prio_r == nil or lowest_prio_r.priority > route.priority then lowest_prio_r = route end end end return lowest_prio_r end function evaluateNode (node, source) if nodes_info [node.id] == nil then return end -- Get node info local node_state = nodes_info [node.id].state local node_api = nodes_info [node.id].api local node_dev_id = nodes_info [node.id].dev_id local node_cpd = nodes_info [node.id].cpd -- Don't do anything if node was not running if node_state ~= "running" then return end -- Emite event if setting is enabled for this API local mute_alsa = Settings.get_boolean ("device.routes.mute-on-alsa-playback-removed") local mute_bluez = Settings.get_boolean ("device.routes.mute-on-bluetooth-playback-removed") if (mute_alsa and node_api == "alsa") or (mute_bluez and node_api == "bluez5") then local e = source:call ("create-event", "mute-alsa-devices", nil, nil) e:set_data ("device-id", node_dev_id) e:set_data ("card-profile-device", node_cpd) EventDispatcher.push_event (e) end end mute_alsa_devices_hook = SimpleEventHook { name = "device/mute-alsa-devices", interests = { EventInterest { Constraint { "event.type", "=", "mute-alsa-devices" }, }, }, execute = function (event) local source = event:get_source () local dev_id = tonumber (event:get_data ("device-id")) local cpd = tonumber (event:get_data ("card-profile-device")) local device_om = source:call ("get-object-manager", "device") local send_notification = false -- We mute all available output ALSA routes but the one associated with -- the running node. -- -- We also don't mute any routes if the running node is associated with -- the lowest priority route as this is most likely to be the Speakers. -- -- For instance, we want to mute all routes except the Headphones one -- when unplugging a headset while playing audio, but we don't -- want to mute the Headphones route when a headset is plugged in while -- playing audio on the Speakers. for device in device_om:iterate() do local dev_bound_id = device["bound-id"] if device.properties["device.api"] == "alsa" then local lpr = findLowestPriorityAvailableOutputRoute (device) if lpr == nil or lpr.device ~= cpd or dev_bound_id ~= dev_id then for p in device:iterate_params("Route") do local route = cutils.parseParam (p, "Route") if route and route.direction == "Output" and route.available ~= "no" and (route.device ~= cpd or dev_bound_id ~= dev_id) then setRoute (device, route, true) send_notification = true end end end end end -- Send notification if devices were muted notifications = notifications or Plugin.find("notifications-api") if notifications ~= nil and send_notification then notifications:call ("send", I18n.gettext("Audio was auto-muted"), I18n.gettext("Active playback device was disconnec