Skip to content
Snippets Groups Projects
Commit c29d701e authored by George Kiagiadakis's avatar George Kiagiadakis
Browse files

monitor-alsa: add device reservation logic

parent 4a15ad05
No related branches found
No related tags found
No related merge requests found
......@@ -7,7 +7,7 @@
Config = {
use_acp = true,
--use_device_reservation = true,
use_device_reservation = true,
enable_midi = true,
enable_jack_client = false,
}
......@@ -25,6 +25,10 @@ if Config.enable_jack_client then
})
end
if Config.use_device_reservation then
rd_plugin = Plugin("reserve-device")
end
function createNode(parent, id, type, factory, properties)
local dev_props = parent.properties
local dev = properties["api.alsa.pcm.device"] or properties["alsa.device"] or "0"
......@@ -140,13 +144,100 @@ function createDevice(parent, id, type, factory, properties)
factory = "api.alsa.acp.device"
end
-- create the device
local device = SpaDevice(factory, properties)
device:connect("create-object", createNode)
device:activate(Feature.SpaDevice.ENABLED | Feature.Proxy.BOUND)
parent:store_managed_object(id, device)
-- use device reservation, if available
if rd_plugin then
local rd_name = "Audio" .. properties["api.alsa.card"]
local rd = rd_plugin:call("create-reservation",
rd_name, "WirePlumber", properties["device.name"], -20);
properties["api.dbus.ReserveDevice1"] = rd_name
-- unlike pipewire-media-session, this logic here keeps the device
-- acquired at all times and destroys it if someone else acquires
rd:connect("notify::state", function (rd, pspec)
local state = rd["state"]
if state == "acquired" then
-- create the device
local device = SpaDevice(factory, properties)
device:connect("create-object", createNode)
device:activate(Feature.SpaDevice.ENABLED | Feature.Proxy.BOUND)
parent:store_managed_object(id, device)
elseif state == "available" then
-- attempt to acquire again
rd:call("acquire")
elseif state == "busy" then
-- destroy the device
parent:store_managed_object(id, nil)
end
end)
if jack_device then
rd:connect("notify::owner-name-changed", function (rd, pspec)
if rd["state"] == "busy" and
rd["owner-application-name"] == "Jack audio server" then
-- TODO enable the jack device
else
-- TODO disable the jack device
end
end)
end
rd:call("acquire")
else
-- create the device
local device = SpaDevice(factory, properties)
device:connect("create-object", createNode)
device:activate(Feature.SpaDevice.ENABLED | Feature.Proxy.BOUND)
parent:store_managed_object(id, device)
end
end
monitor = SpaDevice("api.alsa.enum.udev")
monitor:connect("create-object", createDevice)
monitor:activate(Feature.SpaDevice.ENABLED)
function activateMonitor()
if rd_plugin then
monitor:connect("object-removed", function (parent, id)
local device = parent:get_managed_object(id)
local rd_name = device.properties["api.dbus.ReserveDevice1"]
if rd_name then
rd_plugin:call("destroy-reservation", rd_name)
end
end)
end
Log.info("Activating ALSA monitor")
monitor:activate(Feature.SpaDevice.ENABLED)
end
if rd_plugin then
-- delay activation until the d-bus connection is ready
if rd_plugin["state"] == "connecting" then
rd_plugin:connect("notify::state", function (rdp, pspec)
-- "connected" -> ready
if rd_plugin["state"] == "connected" then
activateMonitor()
-- "closed" -> the d-bus connection failed
elseif rd_plugin["state"] == "closed" then
rd_plugin = nil
activateMonitor()
end
-- TODO disconnect signal handler
end)
-- d-bus connection has failed
elseif rd_plugin["state"] == "closed" then
rd_plugin = nil
activateMonitor()
-- d-bus connection is ready
elseif rd_plugin["state"] == "connected" then
activateMonitor()
end
else
activateMonitor()
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment