simple-awesome/simple/media_control.lua

227 lines
6.8 KiB
Lua

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