This wiki will shut down!
Please note that this wiki will be made read-only and eventually be taken offline.
A replacement is being discussed at https://github.com/awesomeWM/awesome-www/issues/7. We'd be happy to have more input for that discussion and volunteers who help us migrate the content of this wiki to its replacement.
Farhavens volume widget
Contents
Introduction[edit]
This guide walks you through setting up a volume widget for Awesome 3, very much similar to Woffles Volume Widget. In fact, originally this was his volume widget, I adapted it to Awesome 3's Lua syntax and gave it a little pepper with Luas string manipulation functions.
The widget works like this:
- You'll have the volume displayed in your status bar, followed by a % sign if the channel is unmuted and M if it's muted
- Pressing the left mouse-button on the widget will toggle muting
- Scrolling up or down will change the volume
- (Optional) Your media keys (if you have any) will control the volume as long as you are inside your X session and it is not locked
You'll need the following for this widget to work:
- amixer
- awesome 3 (something >= 3.1)
Note on point 2: It should be fairly simple to adapt this widget to the 3.0 release version, it's only that this exact code will not work with the stable release and earlier GIT versions. This widget has been tested and is working on 3.4.10.
Preparation[edit]
The preparation is the same as with Woffles Volume Widget.
Adding the widget[edit]
Add this widget definition to your rc.lua:
tb_volume = widget({ type = "textbox", name = "tb_volume", align = "right" }) tb_volume:buttons({ button({ }, 4, function () volume("up", tb_volume) end), button({ }, 5, function () volume("down", tb_volume) end), button({ }, 1, function () volume("mute", tb_volume) end) }) volume("update", tb_volume)
don't forget to add the widget tb_volume to your widget box like this:
wi_widgets[s]:widgets({ tl_taglist, lb_layout[s], tb_prompt, tl_tasklist, tb_volume, tb_clock })
Bringing the widget to life[edit]
Now it's time to bring the widget to life, using the following code. Paste it right at the beginning of your rc.lua, below those lines starting with require. Change the value of cardid to the ID of your card and the value of channel to the channel you want to manage.
cardid = 0 channel = "Master" function volume (mode, widget) if mode == "update" then local fd = io.popen("amixer -c " .. cardid .. " -- sget " .. channel) local status = fd:read("*all") fd:close() local volume = string.match(status, "(%d?%d?%d)%%") volume = string.format("% 3d", volume) status = string.match(status, "%[(o[^%]]*)%]") if string.find(status, "on", 1, true) then volume = volume .. "%" else volume = volume .. "M" end widget.text = volume elseif mode == "up" then io.popen("amixer -q -c " .. cardid .. " sset " .. channel .. " 5%+"):read("*all") volume("update", widget) elseif mode == "down" then io.popen("amixer -q -c " .. cardid .. " sset " .. channel .. " 5%-"):read("*all") volume("update", widget) else io.popen("amixer -c " .. cardid .. " sset " .. channel .. " toggle"):read("*all") volume("update", widget) end end
Finally, we will be adding a timer hook to refresh the volume display every 10 seconds to reflect changes made by, for example, alsamixer:
awful.hooks.timer.register(10, function () volume("update", tb_volume) end)
This line should be pasted at the end of your rc.lua
Optional stuff[edit]
Setting keybindings[edit]
If you have multimedia keys on your keyboard which currently do nothing but look nice, you may want to add these lines to your rc.lua:
globalkeys = awful.util.table.join(globalkeys, awful.key({ }, "XF86AudioRaiseVolume",function () volume("up", tb_volume) end)) globalkeys = awful.util.table.join(globalkeys, awful.key({ }, "XF86AudioLowerVolume",function () volume("down", tb_volume) end)) globalkeys = awful.util.table.join(globalkeys, awful.key({ }, "XF86AudioMute",function () volume("mute", tb_volume) end))
Or use 'xev' and see what keycode those buttons have then do something like:
globalkeys = awful.util.table.join(globalkeys, awful.key({ }, "#176",function () volume("up", tb_volume) end))
Calmar's mod[edit]
Calmar has modded this widget to contain a progressbar instead of a textbox.
An example progressbar for it:
pb_volume = widget({ type = "progressbar", name = "pb_volume", align = "right" }) pb_volume.width = 12 pb_volume.height = 1 pb_volume.border_padding = 1 pb_volume.border_width = 1 pb_volume.ticks_count = 8 pb_volume.gap = 0 pb_volume.vertical = true pb_volume:bar_properties_set("vol", { ["bg"] = "#000000", ["fg"] = "green", ["fg_center"] = "yellow", ["fg_end"] = "red", ["fg_off"] = "black", ["border_color"] = "#999933", ["min_value"] = 0, ["max_value"] = 100, ["reverse"] = false })
Note: You need to replace every occurence of the old widget name (e.g. in the keybindings) with the new name (pb_volume)
Replace the 3 lines in the original volume(...) function to do stuff on the progressbar, rather than tweaking 'text':
1. volume = volume .. "%" --replace with (set 'normal' bg color): widget:bar_properties_set("vol", {["bg"] = "#000000"}) 2. volume = volume .. "M" --replace with (set 'mute' bg color): widget:bar_properties_set("vol", {["bg"] = "#cc3333"}) 3. widget.text = volume --replace with (just set the value what has to be shown): widget:bar_data_add("vol", volume)
The widget might looks nicer when using 'ticks'. But since the widget is built always homogenuous, you need to tweak the number of ticks (maybe even the height of the widget) to get a not shrunken widget.
I have a good result with 7. (with 6 the widget is shrunken too much. With 8 it can't get drawn (the box will still get drawn!)).
Screenshot:
Farhavens mod[edit]
I myself have also modded this widget to display a an ASCII bar instead of the simple number display. The bar looks like this:
-[||||-----]+
The new code for the volume function would be:
function volume (mode, widget) local cardid = 0 local channel = "Master" if mode == "update" then local status = io.popen("amixer -c " .. cardid .. " -- sget " .. channel):read("*all") local volume = tonumber(string.match(status, "(%d?%d?%d)%%")) status = string.match(status, "%[(o[^%]]*)%]") local color = "#FF0000" if string.find(status, "on", 1, true) then color = "#00FF00" end status = "" for i = 1, math.floor(volume / 10) do status = status .. "|" end for i = math.floor(volume / 10) + 1, 10 do status = status .. "-" end status = "-[" ..status .. "]+" widget.text = "<span color=\"" .. color .. "\">" .. status .. "</span>|" elseif mode == "up" then os.execute("amixer -q -c " .. cardid .. " sset " .. channel .. " 5%+") volume("update", widget) elseif mode == "down" then os.execute("amixer -q -c " .. cardid .. " sset " .. channel .. " 5%-") volume("update", widget) else os.execute("amixer -c " .. cardid .. " sset " .. channel .. " toggle") volume("update", widget) end end
Pavel's mod[edit]
It avoids calling amixer twice. Also, the invocation is easier. The widget definition:
volumecfg = {} volumecfg.cardid = 0 volumecfg.channel = "Master" volumecfg.widget = widget({ type = "textbox", name = "volumecfg.widget", align = "right" }) -- command must start with a space! volumecfg.mixercommand = function (command) local fd = io.popen("amixer -c " .. volumecfg.cardid .. command) local status = fd:read("*all") fd:close() local volume = string.match(status, "(%d?%d?%d)%%") volume = string.format("% 3d", volume) status = string.match(status, "%[(o[^%]]*)%]") if string.find(status, "on", 1, true) then volume = volume .. "%" else volume = volume .. "M" end volumecfg.widget.text = volume end volumecfg.update = function () volumecfg.mixercommand(" sget " .. volumecfg.channel) end volumecfg.up = function () volumecfg.mixercommand(" sset " .. volumecfg.channel .. " 5%+") end volumecfg.down = function () volumecfg.mixercommand(" sset " .. volumecfg.channel .. " 5%-") end volumecfg.toggle = function () volumecfg.mixercommand(" sset " .. volumecfg.channel .. " toggle") end volumecfg.widget:buttons(awful.util.table.join( awful.button({ }, 4, function () volumecfg.up() end), awful.button({ }, 5, function () volumecfg.down() end), awful.button({ }, 1, function () volumecfg.toggle() end) )) volumecfg.update()
Add the following to your widget list:
volumecfg.widget
And try the following key bindings:
globalkeys = awful.util.table.join(globalkeys, awful.key({ }, "XF86AudioRaiseVolume",function () volumecfg.up() end)) globalkeys = awful.util.table.join(globalkeys, awful.key({ }, "XF86AudioLowerVolume",function () volumecfg.down() end)) globalkeys = awful.util.table.join(globalkeys, awful.key({ }, "XF86AudioMute",function () volumecfg.toggle() end))
And the following sample hook:
awful.hooks.timer.register(60, function () volumecfg.update() end)