Add support for sources (i.e. microphones)
The widget will to its best to detect the active source. - Updated client code to detect source changes and add object path information to the volume and mute updated signals. - Added new functions to toggle mute and change volume on the microphone. The functions name have `_mic` appended. - Refactored widget code to reduce duplication. - Updated README with examples on how to add controls for the microphone to `rc.lua`.
This commit is contained in:
parent
a80a9a39b6
commit
8a357e481f
|
@ -92,9 +92,14 @@ Finally add some keyboard shortcuts to control the volume:
|
|||
|
||||
``` lua
|
||||
awful.util.table.join(
|
||||
-- Audio
|
||||
awful.key({ }, "XF86AudioRaiseVolume", pulse.volume_up),
|
||||
awful.key({ }, "XF86AudioLowerVolume", pulse.volume_down),
|
||||
awful.key({ }, "XF86AudioMute", pulse.toggle_muted)
|
||||
awful.key({ }, "XF86AudioMute", pulse.toggle_muted),
|
||||
-- Microphone
|
||||
awful.key({"Shift"}, "XF86AudioRaiseVolume", pulse.volume_up_mic),
|
||||
awful.key({"Shift"}, "XF86AudioLowerVolume", pulse.volume_down_mic),
|
||||
awful.key({ }, "XF86MicMute", pulse.toggle_muted_mic),
|
||||
)
|
||||
```
|
||||
|
||||
|
|
|
@ -78,6 +78,18 @@ function widget:update_sink(object_path)
|
|||
self.sink = pulse.get_device(self.connection, object_path)
|
||||
end
|
||||
|
||||
function widget:update_source(sources)
|
||||
for _, source_path in ipairs(sources) do
|
||||
local s = pulse.get_device(self.connection, source_path)
|
||||
if s.Name and not s.Name:match("%.monitor$") then
|
||||
self.source = s
|
||||
break
|
||||
else
|
||||
self.source = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function widget.volume_up()
|
||||
if not widget.sink:is_muted() then
|
||||
widget.sink:volume_up()
|
||||
|
@ -94,6 +106,24 @@ function widget.toggle_muted()
|
|||
widget.sink:toggle_muted()
|
||||
end
|
||||
|
||||
function widget.volume_up_mic()
|
||||
if widget.source and not widget.source:is_muted() then
|
||||
widget.source:volume_up()
|
||||
end
|
||||
end
|
||||
|
||||
function widget.volume_down_mic()
|
||||
if widget.source and not widget.source:is_muted() then
|
||||
widget.source:volume_down()
|
||||
end
|
||||
end
|
||||
|
||||
function widget.toggle_muted_mic()
|
||||
if widget.source then
|
||||
widget.source:toggle_muted()
|
||||
end
|
||||
end
|
||||
|
||||
function widget:kill_client()
|
||||
if type(self.server_pid) == "number" then
|
||||
awful.spawn("kill -TERM " .. self.server_pid)
|
||||
|
@ -102,30 +132,41 @@ end
|
|||
|
||||
function widget:run_client()
|
||||
|
||||
local function update_after_signal(line, regex, sub, sep)
|
||||
sep = sep or " "
|
||||
local v, found = line:gsub(regex, sub)
|
||||
if found ~= 0 then
|
||||
local idx = v:find(sep)
|
||||
local vol = v:sub(1, idx - 1)
|
||||
local path = v:sub(idx + 1)
|
||||
if path:find("/sink%d+$") then
|
||||
self:update_appearance(vol)
|
||||
self.notify(vol)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local pid = awful.spawn.with_line_callback(
|
||||
[[lua -e 'require("pulseaudio_widget_client")']],
|
||||
{
|
||||
stdout = function (line)
|
||||
local v, found, _
|
||||
|
||||
v, found = line:gsub("^(VolumeUpdated:%s+)(%d)", "%2")
|
||||
if found ~= 0 then
|
||||
self:update_appearance(v)
|
||||
widget.notify(v)
|
||||
end
|
||||
update_after_signal(line, "^(VolumeUpdated:%s+)(%d+)(|)([%w/]+)", "%2 %4")
|
||||
|
||||
v, found = line:gsub("^(MuteUpdated:%s+)(%w)", "%2")
|
||||
if found ~= 0 then
|
||||
self:update_appearance(v)
|
||||
widget.notify(v)
|
||||
end
|
||||
update_after_signal(line, "^(MuteUpdated:%s+)(%w+)(|)([%w/]+)", "%2 %4")
|
||||
|
||||
local v, found
|
||||
v, found = line:gsub("^(NewSink:%s+)(/.*%w)", "%2")
|
||||
if found ~=0 then
|
||||
self:update_sink(v)
|
||||
local volume = self.sink:is_muted() and "Muted" or self.sink:get_volume_percent()[1]
|
||||
self:update_appearance(volume)
|
||||
widget.notify(volume)
|
||||
self.notify(volume)
|
||||
end
|
||||
|
||||
v, found = line:gsub("^(NewSource:%s+)(/.*%w)", "%2")
|
||||
if found ~=0 then
|
||||
self:update_source({v})
|
||||
end
|
||||
end
|
||||
})
|
||||
|
@ -154,8 +195,10 @@ function widget:init()
|
|||
|
||||
self.connection = pulse.get_connection(address)
|
||||
self.core = pulse.get_core(self.connection)
|
||||
local sink_path = assert(self.core:get_sinks()[1], "No sinks found")
|
||||
|
||||
self:update_source(self.core:get_sources())
|
||||
|
||||
local sink_path = assert(self.core:get_sinks()[1], "No sinks found")
|
||||
self:update_sink(sink_path)
|
||||
local volume = self.sink:is_muted() and "Muted" or self.sink:get_volume_percent()[1]
|
||||
self:update_appearance(volume)
|
||||
|
|
|
@ -37,17 +37,31 @@ local address = pulse.get_address()
|
|||
local connection = pulse.get_connection(address)
|
||||
local core = pulse.get_core(connection)
|
||||
local sink = pulse.get_device(connection, core.Sinks[1])
|
||||
local source
|
||||
|
||||
local function get_source(conn, sources)
|
||||
for _, source_path in ipairs(sources) do
|
||||
local s = pulse.get_device(conn, source_path)
|
||||
if s.Name and not s.Name:match("%.monitor$") then
|
||||
return s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
source = get_source(connection, core.Sources)
|
||||
|
||||
-- listen on ALL objects as sinks may change
|
||||
core:ListenForSignal("org.PulseAudio.Core1.Device.VolumeUpdated", {})
|
||||
core:ListenForSignal("org.PulseAudio.Core1.Device.MuteUpdated", {})
|
||||
|
||||
local function connect_sink(s)
|
||||
local function connect_device(s)
|
||||
|
||||
if s.signals.VolumeUpdated then
|
||||
s:connect_signal(
|
||||
function (self, vols)
|
||||
local v = math.ceil(tonumber(vols[1][1]) / self.BaseVolume * 100)
|
||||
print(string.format("VolumeUpdated: %s", v))
|
||||
-- FIXME: BaseVolume for sources (i.e. microphones) won't give the correct percentage
|
||||
print(string.format("VolumeUpdated: %s|%s", v, self.object_path))
|
||||
end,
|
||||
"VolumeUpdated"
|
||||
)
|
||||
|
@ -55,27 +69,42 @@ local function connect_sink(s)
|
|||
|
||||
if s.signals.MuteUpdated then
|
||||
s:connect_signal(
|
||||
function (_, is_mute)
|
||||
function (self, is_mute)
|
||||
local m = is_mute[1] and "Muted" or "Unmuted"
|
||||
print(string.format("MuteUpdated: %s", m))
|
||||
print(string.format("MuteUpdated: %s|%s", m, self.object_path))
|
||||
end,
|
||||
"MuteUpdated"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
connect_sink(sink)
|
||||
connect_device(sink)
|
||||
if source then
|
||||
connect_device(source)
|
||||
end
|
||||
|
||||
core:ListenForSignal("org.PulseAudio.Core1.NewSink", {core.object_path})
|
||||
core:connect_signal(
|
||||
function (_, newsinks)
|
||||
print(string.format("NewSink: %s", newsinks[1]))
|
||||
sink = pulse.get_device(connection, newsinks[1])
|
||||
connect_sink(sink)
|
||||
connect_device(sink)
|
||||
end,
|
||||
"NewSink"
|
||||
)
|
||||
|
||||
core:ListenForSignal("org.PulseAudio.Core1.NewSource", {core.object_path})
|
||||
core:connect_signal(
|
||||
function (_, newsources)
|
||||
print(string.format("NewSource: %s", newsources[1]))
|
||||
source = get_source(connection, newsources)
|
||||
if source then
|
||||
connect_device(source)
|
||||
end
|
||||
end,
|
||||
"NewSource"
|
||||
)
|
||||
|
||||
-- Start the client. Send SIGTERM to stop it.
|
||||
print("Starting Awesome PulseAudio Widget Client")
|
||||
GLib.MainLoop():run()
|
||||
|
|
Loading…
Reference in New Issue