media_control.lua: make volume management fully async

This commit is contained in:
Alice Gaudon 2021-04-08 12:42:13 +02:00
parent e8a91d98ce
commit 0bda31d908
2 changed files with 184 additions and 165 deletions

View File

@ -187,6 +187,7 @@ theme.volume_osd_border_color = theme.border_normal
theme.volume_osd_border_width = dpi(0) theme.volume_osd_border_width = dpi(0)
theme.volume_osd_progress_bg = theme.bg_minimize theme.volume_osd_progress_bg = theme.bg_minimize
theme.volume_osd_progress_color = "#ffffff" theme.volume_osd_progress_color = "#ffffff"
theme.volume_osd_progress_color_muted = "#555555"
theme.volume_osd_progress_border_color = theme.volume_osd_border_color theme.volume_osd_progress_border_color = theme.volume_osd_border_color
theme.volume_osd_progress_border_width = dpi(0) theme.volume_osd_progress_border_width = dpi(0)
theme.volume_osd_image_color = "#ffffff" theme.volume_osd_image_color = "#ffffff"

View File

@ -23,109 +23,116 @@ local config = require("config")
local hasPlayerctl = os.execute("playerctl -v") == true local hasPlayerctl = os.execute("playerctl -v") == true
-- playerctl -- playerctl
function sendToPlayerctl(command) function sendToPlayerctl(command, callback)
os.execute("playerctl " .. command) callback = callback or function()
end
awful.spawn.easy_async("playerctl " .. command, callback)
end end
-- Spotify -- Spotify
function sendToSpotify(command) function sendToSpotify(command, callback)
awful.util.spawn_with_shell("dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player." .. command) callback = callback or function()
end
awful.spawn.easy_async_with_shell("dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player." .. command, callback)
end end
-- Brightness control -- Brightness control
function getBrightness() function getBrightness(callback)
local handle = io.popen("xbacklight -get") callback = callback or function()
local brightness = handle:read("*a") end
handle:close()
return brightness awful.spawn.easy_async("xbacklight -get", function(stdout, stderr, reason, exit_code)
callback(stdout)
end)
end end
function increaseBrightness() function increaseBrightness(callback)
os.execute("xbacklight -inc 2") callback = callback or function()
end
awful.spawn.easy_async("xbacklight -inc 2", callback)
end end
function decreaseBrightness() function decreaseBrightness(callback)
os.execute("xbacklight -dec 2") callback = callback or function()
end
awful.spawn.easy_async("xbacklight -dec 2", callback)
end end
-- Volume control -- Volume control
function getVolume() function isMuted(callback)
if isMuted() then return 0 end awful.spawn.easy_async_with_shell("amixer " .. config.audio.card .. " sget '" .. config.audio.device .. "' | egrep 'Playback.*?\\[o' | egrep -o '\\[o.+\\]'", function(stdout, stderr, reason, exit_code)
local handle = io.popen("amixer " .. config.audio.card .. " sget '" .. config.audio.device .. "' -M | awk -F\"[][]\" '/%/ { print $2 }' | head -n 1", "r") callback(string.match(string.gsub(stdout, "[\n]+", ""), "off"))
local volume = string.gsub(handle:read("*a"), "[\n%%]+", "") / 100 end)
handle:close()
return volume
end end
function isMuted() function getVolume(callback)
local handle = io.popen("amixer " .. config.audio.card .. " sget '" .. config.audio.device .. "' | egrep 'Playback.*?\\[o' | egrep -o '\\[o.+\\]'", "r") awful.spawn.easy_async_with_shell("amixer " .. config.audio.card .. " sget '" .. config.audio.device .. "' -M | awk -F\"[][]\" '/%/ { print $2 }' | head -n 1", function(stdout, stderr, reason, exit_code)
local muted = string.match(string.gsub(handle:read("*a"), "[\n]+", ""), "off") callback(string.gsub(stdout, "[\n%%]+", "") / 100)
handle:close() end)
return muted
end end
function getVolumeImage(volume) function getVolumeImage(volume)
local path = beautiful.volume_osd_icon_3 local path = beautiful.volume_osd_icon_3
if volume < 0.667 then if volume < 0.667 then
path = beautiful.volume_osd_icon_2 path = beautiful.volume_osd_icon_2
end end
if volume < 0.334 then if volume < 0.334 then
path = beautiful.volume_osd_icon_1 path = beautiful.volume_osd_icon_1
end end
if volume <= 0 then if volume <= 0 then
path = beautiful.volume_osd_icon_0 path = beautiful.volume_osd_icon_0
end end
return gears.color.recolor_image(path, beautiful.volume_osd_image_color) return gears.color.recolor_image(path, beautiful.volume_osd_image_color)
end end
local volumeWibox = wibox({ local volumeWibox = wibox({
ontop = true, ontop = true,
bg = beautiful.volume_osd_bg, bg = beautiful.volume_osd_bg,
border_width = beautiful.volume_osd_border_width, border_width = beautiful.volume_osd_border_width,
border_color = beautiful.volume_osd_border_color, border_color = beautiful.volume_osd_border_color,
shape = beautiful.volume_osd_shape, shape = beautiful.volume_osd_shape,
width = beautiful.volume_osd_width, width = beautiful.volume_osd_width,
height = beautiful.volume_osd_bar_height + beautiful.volume_osd_padding * 3, height = beautiful.volume_osd_bar_height + beautiful.volume_osd_padding * 3,
widget = wibox.widget { widget = wibox.widget {
{ {
{ {
image = getVolumeImage(1), image = getVolumeImage(1),
widget = wibox.widget.imagebox widget = wibox.widget.imagebox
}, },
left = beautiful.volume_osd_padding, left = beautiful.volume_osd_padding,
right = beautiful.volume_osd_padding, right = beautiful.volume_osd_padding,
top = beautiful.volume_osd_padding, top = beautiful.volume_osd_padding,
bottom = 0, bottom = 0,
widget = wibox.container.margin, widget = wibox.container.margin,
}, },
{ {
{ {
{ {
max_value = 1, max_value = 1,
value = 0.33, value = 0.33,
shape = gears.shape.rounded_bar, shape = gears.shape.rounded_bar,
bar_shape = gears.shape.rounded_bar, bar_shape = gears.shape.rounded_bar,
margins = beautiful.volume_osd_padding + 4, margins = beautiful.volume_osd_padding + 4,
color = beautiful.volume_osd_progress_color, color = beautiful.volume_osd_progress_color,
background_color = beautiful.volume_osd_progress_bg, background_color = beautiful.volume_osd_progress_bg,
border_color = beautiful.volume_osd_progress_border_color, border_color = beautiful.volume_osd_progress_border_color,
border_width = beautiful.volume_osd_progress_border_width, border_width = beautiful.volume_osd_progress_border_width,
widget = wibox.widget.progressbar widget = wibox.widget.progressbar
}, },
forced_width = 80, forced_width = 80,
forced_height = 80, forced_height = 80,
direction = "east", direction = "east",
layout = wibox.container.rotate, layout = wibox.container.rotate,
}, },
left = beautiful.volume_osd_padding, left = beautiful.volume_osd_padding,
right = beautiful.volume_osd_padding, right = beautiful.volume_osd_padding,
top = 0, top = 0,
bottom = beautiful.volume_osd_padding, bottom = beautiful.volume_osd_padding,
widget = wibox.container.margin, widget = wibox.container.margin,
}, },
layout = wibox.layout.align.vertical layout = wibox.layout.align.vertical
}, },
}) })
local imagebox = volumeWibox.widget:get_children()[1]:get_children()[1] local imagebox = volumeWibox.widget:get_children()[1]:get_children()[1]
@ -135,116 +142,127 @@ local timer = nil
-- {{{ Control -- {{{ Control
local playPause = function() local playPause = function()
if hasPlayerctl then if hasPlayerctl then
sendToPlayerctl("play-pause") sendToPlayerctl("play-pause")
else else
sendToSpotify("PlayPause") sendToSpotify("PlayPause")
end end
end end
local nextTrack = function() local nextTrack = function()
if hasPlayerctl then if hasPlayerctl then
sendToPlayerctl("next") sendToPlayerctl("next")
else else
sendToSpotify("Next") sendToSpotify("Next")
end end
end end
local previousTrack = function() local previousTrack = function()
if hasPlayerctl then if hasPlayerctl then
sendToPlayerctl("previous") sendToPlayerctl("previous")
else else
sendToSpotify("Previous") sendToSpotify("Previous")
end end
end end
local displayVolume = function() local displayVolume = function()
-- Update screen isMuted(function(muted)
local screen = awful.screen:focused() getVolume(function(volume)
volumeWibox.screen = screen -- Update values
imagebox.image = getVolumeImage(muted and 0 or volume)
progressbar.value = volume
progressbar.color = muted and beautiful.volume_osd_progress_color_muted or beautiful.volume_osd_progress_color
-- Position if timer ~= nil and timer.started then
local position = beautiful.volume_osd_position(screen.geometry.width, screen.geometry.height, beautiful.volume_osd_width, beautiful.volume_osd_height) timer:again()
volumeWibox:geometry({ return
x = (screen.geometry.x + position[1]), end
y = (screen.geometry.y + position[2])
})
-- Get volume -- Update screen
local volume = getVolume() local screen = awful.screen:focused()
volumeWibox.screen = screen
-- Update values -- Position
imagebox.image = getVolumeImage(volume) local position = beautiful.volume_osd_position(screen.geometry.width, screen.geometry.height, beautiful.volume_osd_width, beautiful.volume_osd_height)
progressbar.value = volume volumeWibox:geometry({
x = (screen.geometry.x + position[1]),
y = (screen.geometry.y + position[2])
})
-- Show -- Show
volumeWibox.visible = true volumeWibox.visible = true
-- Schedule hide -- Schedule hide
if timer ~= nil then if timer ~= nil then
timer:stop() timer:stop()
end end
timer = gears.timer { timer = gears.timer {
timeout = config.volume_osd_timeout, timeout = config.volume_osd_timeout,
callback = function() callback = function()
volumeWibox.visible = false volumeWibox.visible = false
timer:stop() timer:stop()
timer = nil timer = nil
end end
} }
timer:start() timer:start()
end)
end)
end end
local raiseVolume = function() local raiseVolume = function()
os.execute("amixer " .. config.audio.card .. " set '" .. config.audio.device .. "' 5%+ -M") awful.spawn.easy_async("amixer " .. config.audio.card .. " set '" .. config.audio.device .. "' 5%+ -M", function(stdout, stderr, reason, exit_code)
displayVolume() displayVolume()
end)
end end
local lowerVolume = function() local lowerVolume = function()
os.execute("amixer " .. config.audio.card .. " set '" .. config.audio.device .. "' 5%- -M") awful.spawn.easy_async("amixer " .. config.audio.card .. " set '" .. config.audio.device .. "' 5%- -M", function(stdout, stderr, reason, exit_code)
displayVolume() displayVolume()
end)
end end
local toggleMute = function() local toggleMute = function()
local muted = isMuted() isMuted(function(muted)
os.execute("amixer " .. config.audio.card .. " set '" .. config.audio.device .. "' " .. (muted and 'on' or 'off')) awful.spawn.easy_async("amixer " .. config.audio.card .. " set '" .. config.audio.device .. "' " .. (muted and 'on' or 'off'), function(stdout, stderr, reason, exit_code)
displayVolume() displayVolume()
end)
end)
end end
-- }}} -- }}}
function getKeys(keys) function getKeys(keys)
if config.audio.card == 'disabled' then if config.audio.card == 'disabled' then
return return
-- Media control -- Media control
hotkey.make(keys.playPause, playPause, hotkey.make(keys.playPause, playPause,
{ description = "Toggle Play / Pause", group = "media control" }), { description = "Toggle Play / Pause", group = "media control" }),
hotkey.make(keys.nextTrack, nextTrack, hotkey.make(keys.nextTrack, nextTrack,
{ description = "Next track", group = "media control" }), { description = "Next track", group = "media control" }),
hotkey.make(keys.previousTrack, previousTrack, hotkey.make(keys.previousTrack, previousTrack,
{ description = "Previous track", group = "media control" }) { description = "Previous track", group = "media control" })
end end
return return
-- Volume control -- Volume control
hotkey.make(keys.raiseVolume, raiseVolume, hotkey.make(keys.raiseVolume, raiseVolume,
{ description = "Raise volume", group = "media control" }), { description = "Raise volume", group = "media control" }),
hotkey.make(keys.lowerVolume, lowerVolume, hotkey.make(keys.lowerVolume, lowerVolume,
{ description = "Lower volume", group = "media control" }), { description = "Lower volume", group = "media control" }),
hotkey.make(keys.toggleMute, toggleMute, hotkey.make(keys.toggleMute, toggleMute,
{ description = "Toggle mute audio", group = "media control" }), { description = "Toggle mute audio", group = "media control" }),
-- Media control -- Media control
hotkey.make(keys.playPause, playPause, hotkey.make(keys.playPause, playPause,
{ description = "Toggle Play / Pause", group = "media control" }), { description = "Toggle Play / Pause", group = "media control" }),
hotkey.make(keys.nextTrack, nextTrack, hotkey.make(keys.nextTrack, nextTrack,
{ description = "Next track", group = "media control" }), { description = "Next track", group = "media control" }),
hotkey.make(keys.previousTrack, previousTrack, hotkey.make(keys.previousTrack, previousTrack,
{ description = "Previous track", group = "media control" }), { description = "Previous track", group = "media control" }),
-- Backlight control -- Backlight control
hotkey.make(keys.brightnessUp, increaseBrightness, hotkey.make(keys.brightnessUp, increaseBrightness,
{ description = "Increase screen backlight brightness", group = "media control"}), { description = "Increase screen backlight brightness", group = "media control" }),
hotkey.make(keys.brightnessDown, decreaseBrightness, hotkey.make(keys.brightnessDown, decreaseBrightness,
{ description = "Decrease screen backlight brightness", group = "media control"}) { description = "Decrease screen backlight brightness", group = "media control" })
end end
return { return {
getKeys = getKeys, getKeys = getKeys,
} }