-- -- 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, callback) callback = callback or function() end awful.spawn.easy_async("playerctl " .. command, callback) end -- Spotify function sendToSpotify(command, callback) 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 -- Brightness control function getBrightness(callback) callback = callback or function() end awful.spawn.easy_async("xbacklight -get", function(stdout, stderr, reason, exit_code) callback(stdout) end) end function increaseBrightness(callback) callback = callback or function() end awful.spawn.easy_async("xbacklight -inc 2", callback) end function decreaseBrightness(callback) callback = callback or function() end awful.spawn.easy_async("xbacklight -dec 2", callback) end -- Volume control function isMuted(callback) 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) callback(string.match(string.gsub(stdout, "[\n]+", ""), "off")) end) end function getVolume(callback) 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) callback(string.gsub(stdout, "[\n%%]+", "") / 100) end) 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() isMuted(function(muted) getVolume(function(volume) -- 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 if timer ~= nil and timer.started then timer:again() return end -- 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]) }) -- 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) end) end local raiseVolume = function() awful.spawn.easy_async("amixer " .. config.audio.card .. " set '" .. config.audio.device .. "' 5%+ -M", function(stdout, stderr, reason, exit_code) displayVolume() end) end local lowerVolume = function() awful.spawn.easy_async("amixer " .. config.audio.card .. " set '" .. config.audio.device .. "' 5%- -M", function(stdout, stderr, reason, exit_code) displayVolume() end) end local toggleMute = function() isMuted(function(muted) awful.spawn.easy_async("amixer " .. config.audio.card .. " set '" .. config.audio.device .. "' " .. (muted and 'on' or 'off'), function(stdout, stderr, reason, exit_code) displayVolume() end) end) 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" }), -- Backlight control hotkey.make(keys.brightnessUp, increaseBrightness, { description = "Increase screen backlight brightness", group = "media control" }), hotkey.make(keys.brightnessDown, decreaseBrightness, { description = "Decrease screen backlight brightness", group = "media control" }) end return { getKeys = getKeys, }